I am writing a C# application which uses Interop services to access functions in a native C++ DLL. I am already using about 10 different functions which are working.
Now I am not sure how to handle passing a callback as a parameter so that the DLL can call my code.
Here is the function prototype of the DLL:
typedef void (WINAPI * lpfnFunc)(const char *arg1, const char *arg2)
And the function that allows me to pass the above type:
int WINAPI SetFunc(lpfnFunc f)
Here is my C# code for the delegate and function definitions:
public delegate void Func(string arg1, string arg2); public static void MyFunc(string arg1, string arg2)
Here is my C# code for the SetFunc Interop function:
[DllImport("lib.dll", CharSet = CharSet.Ansi)] public static extern int SetFunc(Func lpfn);
And finally here is the code where I call the SetFunc function and pass it my callback:
SetFunc(new Func(MyFunc));
Unfortunately my function is not being called when it should be. The return value of the SetFunc function is returning the error code for a Success, so either it's not calling my function or it's not working because my code is wrong.
Arguments in C and C++ language are copied to the program stack at run time, where they are read by the function. These arguments can either be values in their own right, or they can be pointers to areas of memory that contain the data being passed. Passing a pointer is also known as passing a value by reference.
Pass by Value, means that a copy of the data is made and stored by way of the name of the parameter. Any changes to the parameter have NO affect on data in the calling function.
By default, LotusScript® passes arguments to functions and subs by reference. If the argument is an array, a user-defined data type variable, or an object reference variable, you must pass it by reference. In most other cases, you use the ByVal keyword to pass variables by value.
This works for me:
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); } }
Can you try changing the Func delegate to
public delegate void Func([In, MarshalAs(UnmanagedType.LPStr)] string arg1, [In, MarshalAs(UnmanagedType.LPStr)] string arg2);
And the SetFunc method to
[DllImport("lib", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Winapi)] public static extern int SetFunc(Func lpfn);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With