سؤال

ملخص:

لدي مجموعة من وظائف ج لا بد لي من الاتصال من C #. يعتمد حل العمل الحالي الخاص بي على التحميل الزائد الوظيفي وأنا أتساءل عما إذا كان هناك حل أكثر أناقة.

الاشياء C:

في مكان ما في ملف رأس

typedef struct _unknown_stuff * handle; // a opaque pointer

مثال على الوظيفة

func( uint      num_entries,
      handle *  objects,
      uint *    n)
{ ... }

في C، يجب استخدام الوظيفة مماثلة لهذا:

// warning: i bet that the syntax is not correct but you should get the idea...

uint n;

func(0, null, &n);

handle * objects = malloc(n * sizeof(handle));

func(n, objects, null);

الأشياء C #:

الآن أفعل ما يلي في C #:

public struct handle
{
    public IntPtr Pointer;
}

// version to get number of objects
[DllImport(dll, ...]
private static extern void
func(  uint        must_be_zero,
       object      must_be_null,
       out uint    n);

// version to get the actual data
[DllImport(dll, ...]
private static extern void
func(   uint           num_entries,
        [Out] handle[] objects,
        int            must_be_zero);

وثم:

handle[] objects;

uint n = 42;

func(0, null, out n);

objects = new handle[n];

func(n, objects, 0);

السؤال

منذ أنا C # Noob، كنت أتساءل عما إذا كانت هذه هي أفضل طريقة للقيام بذلك. خاصة أود أن أعرف ما إذا كان هناك طريقة حول التحميل الزائد في الوظيفة.

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

المحلول

بادئ ذي بدء، رمزك كما هو خاطئ، لأنه في الثانية C # توقيع حجتك الثالثة هي int, ، في حين أن حجة C المقابلة لا تزال int*. وبعد ستعمل عند استهداف نوافذ 32 بت، لأن sizeof(int)==sizeof(int*) هناك - لذلك عند تمرير 0 int، ينتهي بك الأمر تمر بموجب مؤشر فارغ - لكنه ليس آمنا 64 بت. إذا كنت لا تزال ترغب في القيام بذلك بهذه الطريقة، فأنت بحاجة إلى استخدامها IntPtr هناك.

بصرف النظر عن ذلك، يمكنك محاولة:

[DllImport(dll, ...]
private static extern void func(
  uint num_entries,
  [Out] handle[] objects,
  [Out] int[] num_devices);

جعل الوسيطة الثالثة صفيف بحيث يمكنك تمرير NULL هناك.

أو مجرد استخدام المؤشرات. لا يوجد شيء سيء حيال ذلك، ولا تخف من unsafe الكلمة الرئيسية - أي نوع من P / invoke غير آمن بطبيعته على أي حال، لذلك قد تكون واضحة حول هذا الموضوع.

نصائح أخرى

لن ينظر DLL C إلى 0، ومعالجة ذلك تماما؟

لديها وظيفة واحدة فقط، صحيحة؟ وهذا هو، يتم تعريف وظيفة C مرة واحدة، وليس بشكل منفصل لحالة فارغة، ولديها

if( objects == NULL )
تحقق في مكان ما هناك. على معظم الأنظمة (تحقق من STDIO.H من النظام المستهدف)، فهذا هو 0. لذا فإن الاتصال من Pinvoke مع قيمة 0 في هذا المكان يجب أن تفعل ما تريد التحميل الزائد للقيام به.

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