Как правильно исправить структуру из C в C # с явным выравниванием (неуправляемая dll) - PullRequest
0 голосов
/ 22 мая 2018

Я должен использовать неуправляемую DLL (написанную на C) в моем приложении C #.В этой DLL у меня есть структура:

typedef struct {
void (*Func1)(void*, int*);
void (*Func2)(void*, int*);
} myStructure;

и у меня есть функция, которая использует эту структуру в качестве параметра [in / out]:

void functionInterface(myStructure* pToStruct);

в C #, я перевожу этоструктура как:

[StructLayout(LayoutKind.Sequential)]
public unsafe struct myStructure
{
    //defining delegate instances        
    public func1 Func1;
    public func2 Func2;
              ...
    //defining delegate types
    public delegate void Func1(void* l,int* data);
    public delegate void Func2(void* l,int* data);
              ...
}

и функция в C #:

[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void functionInterface(ref myStructure pToStruct);

При вызове этой функцииInterface () во время выполнения возникают исключения. Как "нарушение прав доступа для записи в ...адрес ... "или" нарушение прав доступа для чтения по адресу ... адрес ... "

Я не могу найти причину, я думаю, что проблема может заключаться в правильном выравнивании элементов в переведенной структуре, иливыравнивание стека, но я понятия не имею, как это сделать правильно.Или проблема может быть другой, другой природы, которую я не могу обнаружить, надеюсь, вы поможете мне, ребята.

1 Ответ

0 голосов
/ 22 мая 2018

Это прекрасно работает ... Как я люблю говорить: вы ломаете его, вы ремонтируете его ...

C # сторона:

[StructLayout(LayoutKind.Sequential)]
public struct myStructure
{
    public Fn1 Func1;
    public Fn2 Func2;

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void Fn1(IntPtr p1, ref int p2);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void Fn2(IntPtr p1, ref int p2);
}

[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void functionInterface(out myStructure pToStruct);

А потом:

myStructure myStructure;
functionInterface(out myStructure);

int num1 = 100, num2 = 200;
myStructure.Func1((IntPtr)0x1000, ref num1);
Console.WriteLine("C#-side: out Func1: {0}", num1);
myStructure.Func2((IntPtr)0x2000, ref num2);
Console.WriteLine("C#-side: out Func2: {0}", num2);

C-сторона: (Я поместил весь код в файл .c / .cpp, без заголовка)

#ifdef __cplusplus
extern "C"
{
#endif
    typedef struct 
    {
        void (*Func1)(void*, int*);
        void (*Func2)(void*, int*);
    } myStructure;

    void Fn1(void* p1, int* p2)
    {
        printf("C-side: Fn1: %p, %d - ", p1, *p2);
        *p2 += 1;
    }

    void Fn2(void* p1, int* p2)
    {
        printf("C-side: Fn2: %p, %d - ", p1, *p2);
        *p2 += 1;
    }

    __declspec(dllexport) void functionInterface(myStructure* pToStruct)
    {
        pToStruct->Func1 = Fn1;
        pToStruct->Func2 = Fn2;
    }
#ifdef __cplusplus
}
#endif
...