سؤال

لدي بعض رموز C القياسية ANSI والتي تعتبر موثوقة.ما يعنيه ذلك هو أنه على الرغم من أنني أملك المصدر، إلا أنني لا أستطيع الترجمة إلى لغة أخرى أو تعديل وسيطات الاستدعاء، لأن هذه الإجراءات من شأنها أن تبطل السلطة.هناك أكثر من 150 وظيفة.

يمكنني إجراء تغييرات عرضية، مثل تغيير أسماء الملفات من .C إلى .CPP بحيث يتم تجميعها باستخدام برنامج التحويل البرمجي C++ الخاص بـ Visual Studio 2009، وهو ما قمت به.يمكن أيضًا إضافة توجيهات المترجم وما شابه.يمكنني أيضًا المرور عبر طبقة الغلاف، إذا لزم الأمر.

قيد آخر هو أن شركتي تفعل ذلك لا تريد مني استخدام غير آمن الكلمة الرئيسية في أي كود C#.

أحتاج للحصول على هذه الوظائف من برنامج C#.

تبدو وظيفة C/C++ النموذجية كما يلي:
double SomeFunction(double a, double[3] vec, double[3][3] mat);
حيث تكون محتويات المصفوفة في بعض الأحيان مدخلة، وأحياناً مخرجة، ونادرا ما تكون كلاهما.

لقد حاولت أولاً إنشاء ملف DLL غير مُدار (مع الوظائف المميزة بـ Extern C).تعمل الوظائف التي تحتوي على وسيطات بسيطة فقط (int، double) بشكل جيد، لكن لم أتمكن من تحديد كيفية تنظيم المصفوفات.(في الواقع، لقد وجدت بعض نماذج التعليمات البرمجية، لكنها كانت معقدة للغاية ومن غير المعقول تكرارها 150 مرة.)

ثم قمت بعد ذلك بتجربة مشروعين في نفس الحل، أحدهما بلغة C++ والآخر بلغة C#.في مشروع C++، قمت بإنشاء وظيفة مُدارة والتي تسمى فقط الوظيفة الأصلية التي تم وضع علامة عليها على أنها غير مُدارة.كان هذا واضحًا وبسيطًا للغاية، ومرة ​​أخرى، عملت الحجج البسيطة بشكل جيد.لكن بالنسبة للمصفوفات، لم أتمكن من العثور على كيفية جعل أنواع الوسيطات تتطابق عبر حدود C# إلى C++:
الوسيطة "2":لا يمكن التحويل من 'double[]' إلى 'double*'
(وكما هو مذكور أعلاه، لا يمكنني استخدام غير آمن للحصول على مؤشر).

من المؤكد أن ما أحاول القيام به يجب أن يكون ممكنًا.
ما هي أفضل طريقة للوصول إلى هذه الوظائف؟
(نموذج التعليمات البرمجية باستخدام الوظيفة المذكورة أعلاه سيكون رائعًا حقًا.)

هل كانت مفيدة؟

المحلول

نموذج تنفيذ C/C++:

extern "C" __declspec(dllexport)
double SomeFunction(double a, double vec[3], double mat[3][3]) {
  double sum = a;
  for (int ix = 0; ix < 3; ++ix) {
    sum += vec[ix];
    for (int iy = 0; iy < 3; ++iy) {
      sum += mat[ix][iy];
    }
  }
  return sum;
}

نموذج لاستخدام C#:

private void Form1_Load(object sender, EventArgs e) {
  double[] vec = new double[3];
  double[,] mat = new double[3, 3];
  for (int ix = 0; ix < 3; ++ix) {
    vec[ix] = ix;
    for (int iy = 0; iy < 3; ++iy) {
      mat[ix, iy] = (ix + 1) * iy;
    }
  }
  double sum = SomeFunction(1, vec, mat);
}
[System.Runtime.InteropServices.DllImport("cpptemp8.dll")]
private static extern double SomeFunction(double a, double[] vec, double[,] mat);

نصائح أخرى

إذا لم تتمكن من تشغيل الحل الخارجي وP/Invoc، فمن المحتمل أن يكون المجمّع هو أفضل رهان لك.قم بإنشاء ملف C++ DLL مُدار يستخدم كلاً من التعليمات البرمجية المُدارة وغير المُدارة.قم بإضافة فئة .NET إلى مكتبة الارتباط الحيوي (DLL) هذه التي تعد مجرد غلاف رفيع فوق الوظائف الموجودة في مكتبة الارتباط الحيوي (DLL) الخاصة بك.يمكن لكود C# الخاص بك استدعاء فئة C++ .NET، والتي بدورها ستنتقل إلى وظائف C.

بهذه الطريقة يمكنك كتابة الترجمة بين .NET والتعليمات البرمجية غير المُدارة بنفسك، بدلاً من الاعتماد على وقت التشغيل للقيام بذلك نيابةً عنك.

استخدم swig، وسوف يقوم بإنشاء pinvoc الخاص بك بالنسبة لك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top