Передача функции обратного вызова C # через Interop / pinvoke - PullRequest
22 голосов
/ 01 ноября 2011

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

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

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

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

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

int WINAPI SetFunc(lpfnFunc f)

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

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

public static void MyFunc(string arg1, string arg2)

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

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

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

SetFunc(new Func(MyFunc));

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

Ответы [ 2 ]

16 голосов
/ 15 декабря 2014

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

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

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

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

#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, C #):

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);
    }
}
3 голосов
/ 03 ноября 2011

Можете ли вы попробовать изменить делегат 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);
...