Подтвердить что ты не робот

Передача функции обратного вызова С# через Interop/pinvoke

Я пишу приложение С#, которое использует службы Interop для доступа к функциям в родной С++ DLL. Я уже использую около 10 различных функций, которые работают.

Теперь я не уверен, как обращаться с передачей обратного вызова в качестве параметра, чтобы DLL могла вызвать мой код.

Вот прототип функции DLL:

typedef void (WINAPI * lpfnFunc)(const char *arg1, const char *arg2)

И функция, которая позволяет мне передать вышеуказанный тип:

int WINAPI SetFunc(lpfnFunc f)

Вот мой код С# для определения делегата и функций:

public delegate void Func(string arg1, string arg2);

public static void MyFunc(string arg1, string arg2)

Вот мой код С# для функции SetFunc Interop:

[DllImport("lib.dll", CharSet = CharSet.Ansi)]
public static extern int SetFunc(Func lpfn);

И, наконец, вот код, в котором я вызываю функцию SetFunc и передаю ей свой обратный вызов:

SetFunc(new Func(MyFunc));

К сожалению, моя функция не вызывается, когда она должна быть. Возвращаемое значение функции SetFunc возвращает код ошибки для успеха, поэтому либо он не вызывает мою функцию, либо не работает, потому что мой код неверен.

4b9b3361

Ответ 1

Это работает для меня:

Calc.h(Calc.dll, С++):

extern "C" __declspec(dllexport) double Calc(double x, double y, double __stdcall p(double, double));

Calc.cpp(Calc.dll, С++):

#include "calc.h"

__declspec(dllimport) double Calc(double x, double y, double __stdcall p(double, double))
{
    double s = p(x*x, y*y);
    return x * y + s;
}

Program.cs(Sample.exe, С#):

class Program
{
    delegate double MyCallback(double x, double y);
    [DllImport("Calc.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern double Calc(double x, double y, [MarshalAs(UnmanagedType.FunctionPtr)]MyCallback func);

    static void Main(string[] args)
    {
        double z = Calc(1, 2, (x, y) => 45);
    }
}

Ответ 2

Можете ли вы попробовать изменить делегат Func на

    public delegate void Func([In, MarshalAs(UnmanagedType.LPStr)] string arg1, [In, MarshalAs(UnmanagedType.LPStr)] string arg2);

И метод SetFunc для

[DllImport("lib", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)]
public static extern int SetFunc(Func lpfn);