Как мне вызвать функцию c из C#

#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);