#c# #c #callback
#c# #c #обратный вызов
Вопрос:
Я хотел бы использовать эту функцию C в C#:
typedef void (*WRITE_CALLBACK)(int hMountEnv, unsigned __int64 NumBytesWritten,
void* pContext);
Как бы мне определить ее, чтобы я мог ее вызывать?
Нужно ли мне сделать что-нибудь еще, чтобы это заработало?
Комментарии:
1. в каком контексте это имеет значение? вы хотите использовать какую-нибудь неуправляемую библиотеку в c #? или вы хотите получить «версию c #» указателя на эту функцию?
2. Да, я хочу использовать какую-нибудь неуправляемую библиотеку в C # и получить C # версию указателя на эту функцию.
3. Это объявление указателя на функцию, а не функция. Эквивалент типа делегата в C #. Вы не можете вызвать тип.
4. в таком случае вам следует взглянуть на ссылку, предоставленную AnitKryst … там есть все, что вам нужно
Ответ №1:
Взгляните на http://msdn.microsoft.com/en-us/library/ektebyzx (v = против 80).aspx о том, как маршалировать указатели на функции. В нижней части этой страницы есть пример.
Я сделаю C # для вас, и поскольку я не знаю, в каком направлении движется указатель, я покажу оба. Есть некоторые ошибки, которые могут быть проблематичными для вас, связанные с соглашениями о вызовах. Marshal.GetDelegateForFunctionPointer
и Marshal.GetFunctionPointerForDelegate
предположим, что указателем на функцию будет StdCall, поэтому, если у вас нет доступа к неуправляемой библиотеке, чтобы убедиться, что указатель на функцию является стандартным вызовом (к сожалению, я думаю, что C по умолчанию использует cdecl), вам придется создать неуправляемую библиотеку-оболочку, чтобы изменить соглашение о вызовах, если только нет другого способа, о котором я не знаю.
Это будет заголовок библиотеки DLL C, которую я назвал «UnmanagedLib.dll «.
typedef void ( __stdcall *WRITE_CALLBACK)(int hMountEnv, unsigned __int64 NumBytesWritten, void* pContext);
extern "C" {
__declspec(dllexport) WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void);
__declspec(dllexport) void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback);
}
Это будет CPP-файл библиотеки DLL.
#include "UnmanagedLib.h"
void __stdcall SampleFunction(int hMountEnv, unsigned __int64 NumBytesWritten, void* pContext)
{
}
WRITE_CALLBACK __stdcall FunctionProducingFunctionPointer(void)
{
return amp;SampleFunction;
}
void __stdcall FunctionConsumingFunctionPointer(WRITE_CALLBACK callback)
{
// sample call
(*callback)(0,0,NULL);
}
И, наконец, это программа на C # для использования библиотеки DLL.
class Program
{
public delegate void WRITE_CALLBACK(int hMountEnv, ulong NumBytesWritten, IntPtr pContext);
[DllImport("UnmanagedLib.dll")]
public static extern IntPtr FunctionProducingFunctionPointer();
[DllImport("UnmanagedLib.dll")]
public static extern void FunctionConsumingFunctionPointer(IntPtr functionPointer);
public static void SampleFunction(int hMountEnv, ulong NumBytesWritten, IntPtr pContext)
{
}
static void Main(string[] args)
{
var functionDelegateToManagedSampleFunction = new WRITE_CALLBACK(SampleFunction);
var functionDelegateToUnmanagedSampleFunction = Marshal.GetDelegateForFunctionPointer(FunctionProducingFunctionPointer(), typeof(WRITE_CALLBACK));
// call the unmanaged sample function via its pointer
functionDelegateToUnmanagedSampleFunction.DynamicInvoke(new object[] {0,0ul,null});
// pass the managed sample function to the unmanaged code
FunctionConsumingFunctionPointer(Marshal.GetFunctionPointerForDelegate(functionDelegateToManagedSampleFunction));
}
}
Комментарии:
1. Эта ссылка предназначена для C / CLI (управляемый C ), а не для C #.
2. Спасибо, AnitKryst. Я хочу опубликовать свою основную функцию: int __stdcall WriteFile (int hMountEnv, const char* полностью квалифицированный путь к файлу источника, const char* полностью квалифицированный путь к файлу назначения, const WRITE_CALLBACK pCallbackFunction, void* pContext )
3. Объявите свой делегат с атрибутом [UnmanagedFunctionPointer(вызывающий соглашение. Cdecl)], чтобы изменить ожидаемое соглашение о вызове. Очень удобно!
Ответ №2:
Это больше похоже на делегат, чем на саму функцию / метод. Вы бы не вызывали это, это было бы предоставлено как указатель функции на что-то другое. Эквивалентом может быть что-то вроде этого:
public delegate void WRITE_CALLBACK(int hMountEnv, uint numBytesWritten, object pContext);