Использование делегатов в C # в качестве обратного вызова для функций C DllImported - PullRequest
0 голосов
/ 02 августа 2011

Я пытаюсь вызвать функции DLL C.

Но я получил StackOverflowException, поэтому я думаю, что что-то не так с функцией в качестве параметра.

Подробно это выглядит так.

C DLL (заголовочный файл):

typedef struct
{
  MyType aType;     /* message type */
  int nItems;       /* number of items */
   const MyItems    *lpItem;    /* pointer to array of items */
} MyStruct;

typedef void (__stdcall *MyCbFunc) (HWND, const MyStruct  *);

API(BOOL) RegisterCbFunc (ARGS, MyCbFunc);

В C # я пробовал это:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MyStruct
{
  MyType aType;
  int nItems;
  MyItems[] lpItem;
}

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void CallbackDelegate(MyStruct mStruct);

[DllImport("MY.dll", CallingConvention=CallingConvention.StdCall)]
private static extern int RegisterCbFunc(IntPtr hWnd, Delegate pCB);

public static void MyCbFunc(MyStruct mStruct)
{
  // do something
}

static void Main(string[] args)
{
  CallbackDelegate dCbFunc = new CallbackDelegate(MyCbFunc);
  int returnValue = RegisterCbFunc(IntPtr.Zero, dCbFunc);
  // here, returnValue is 1
}

Это выполняется до тех пор, пока DLL не вызовет функцию обратного вызова. Тогда я получил ошибку:

An unhandled exception of type 'System.StackOverflowException' occurred in Microsoft.VisualStudio.HostingProcess.Utilities.dll

Спасибо за помощь.

ОТВЕТ: Не знаю почему, но был ответ, который сейчас удален?!

Я пытаюсь восстановить его. Решением было использование вызова по ссылке вместо вызова по значению для параметра функции.

public delegate void CallbackDelegate(ref MyStruct mStruct);

1 Ответ

1 голос
/ 02 августа 2011

Ваша функция C ожидает указатель на MyStruct, но вы говорите C #, что она хочет указатель на функцию.Разница между функцией и структурой ... значительна.Возможно, попробуйте что-то вроде

[DllImport("MY.dll", CallingConvention=CallingConvention.StdCall)]
private static extern int RegisterCbFunc(IntPtr hWnd, Delegate pCB);

static void Main(string[] args)
{
MyStruct mStruct;
int returnValue = RegisterCbFunc(IntPtr.Zero, mStruct);
}

Если ваша функция C заполняет член lpItem в MyStruct чем-то, что она выделяет сама, я понятия не имею, что будет дальше, но, по крайней мере, этого не произойдет.пытаясь переписать ваш код.

...