16 Jul 2012 19:31
Question about C# callbacks using cs_callback
Jeremy Treger <jeremy.treger <at> gmail.com>
2012-07-16 17:31:51 GMT
2012-07-16 17:31:51 GMT
Hello,
I am attempting to pass a c# function to C++ as a callback using David Piepgrass's cs_callback function which has been posted to this list several times:
///////////////////////////////////////////////////////////////////////////
// cs_callback is used to marshall callbacks. It allows a C# function to
// be passed to C++ as a function pointer through P/Invoke, which has the
// ability to make unmanaged-to-managed thunks. It does NOT allow you to
// pass C++ function pointers to C#.
//
// Anyway, to use this macro you need to declare the function pointer type
// TYPE in the appropriate header file (including the calling convention),
// declare a delegate named after CSTYPE in your C# project, and use this
// macro in your .i file. Here is an example:
//
// in C++ header file (%include this header in your .i file):
// typedef void (__stdcall *Callback)(PCWSTR);
// void Foo(Callback c);
//
// in C# code:
// public delegate void CppCallback([MarshalAs(UnmanagedType.LPWStr)]
// string message);
//
// in your .i file:
// %cs_callback(Callback, CppCallback)
//
// As an alternative to specifying __stdcall on the C++ side, in the .NET
// Framework (but not the Compact Framework) you can use the following
// attribute on the C# delegate in order to get compatibility with the
// default calling convention of Visual C++ function pointers:
// [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
//
// Remember to invoke %cs_callback BEFORE any code involving Callback.
%define %cs_callback(TYPE, CSTYPE)
%typemap(ctype) TYPE, TYPE& "void*"
%typemap(in) TYPE %{ $1 = ($1_type)$input; %}
%typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
%typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(csin) TYPE, TYPE& "$csinput"
%enddef
Unfortunately, I have not been able to get it to work correctly and I get a build error in C#. My c++ header looks like this:// cs_callback is used to marshall callbacks. It allows a C# function to
// be passed to C++ as a function pointer through P/Invoke, which has the
// ability to make unmanaged-to-managed thunks. It does NOT allow you to
// pass C++ function pointers to C#.
//
// Anyway, to use this macro you need to declare the function pointer type
// TYPE in the appropriate header file (including the calling convention),
// declare a delegate named after CSTYPE in your C# project, and use this
// macro in your .i file. Here is an example:
//
// in C++ header file (%include this header in your .i file):
// typedef void (__stdcall *Callback)(PCWSTR);
// void Foo(Callback c);
//
// in C# code:
// public delegate void CppCallback([MarshalAs(UnmanagedType.LPWStr)]
// string message);
//
// in your .i file:
// %cs_callback(Callback, CppCallback)
//
// As an alternative to specifying __stdcall on the C++ side, in the .NET
// Framework (but not the Compact Framework) you can use the following
// attribute on the C# delegate in order to get compatibility with the
// default calling convention of Visual C++ function pointers:
// [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
//
// Remember to invoke %cs_callback BEFORE any code involving Callback.
%define %cs_callback(TYPE, CSTYPE)
%typemap(ctype) TYPE, TYPE& "void*"
%typemap(in) TYPE %{ $1 = ($1_type)$input; %}
%typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
%typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(csin) TYPE, TYPE& "$csinput"
%enddef
typedef void (__stdcall *Callback)(PCWSTR);
ApplicationIo(Callback c); // ApplicationIo is just my class that will use the callback.
My .i file looks like this:ApplicationIo(Callback c); // ApplicationIo is just my class that will use the callback.
%module II_Interface_DLL
%{
#include "II_Interface_DLL.h" //This is the header file for my DLL
%}
//Other SWIG libs are included here
%define %cs_callback(TYPE, CSTYPE)
%typemap(ctype) TYPE, TYPE& "void*"
%typemap(in) TYPE %{ $1 = ($1_type)$input; %}
%typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
%typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(csin) TYPE, TYPE& "$csinput"
%enddef
%cs_callback(Callback, CppCallback)
%include "II_Interface_DLL.h"
#include "II_Interface_DLL.h" //This is the header file for my DLL
%}
//Other SWIG libs are included here
%define %cs_callback(TYPE, CSTYPE)
%typemap(ctype) TYPE, TYPE& "void*"
%typemap(in) TYPE %{ $1 = ($1_type)$input; %}
%typemap(in) TYPE& %{ $1 = ($1_type)&$input; %}
%typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE"
%typemap(csin) TYPE, TYPE& "$csinput"
%enddef
%cs_callback(Callback, CppCallback)
%include "II_Interface_DLL.h"
public delegate void CppCallback([MarshalAs(UnmanagedType.LPWStr)] string newText);
public void UpdateLog(string newText) { //stuff } // The function I want to pass as the callback
CppCallback logCallback = new CppCallback(this.UpdateLog);
ApplicationIo IO = new ApplicationIo(logCallback); //This is the line where the error gets flagged
The C++ DLL appears to compile just fine with the callback, but when I try to instantiate the ApplicationIo class in C# with my C# delegate, it gives the following error:public void UpdateLog(string newText) { //stuff } // The function I want to pass as the callback
CppCallback logCallback = new CppCallback(this.UpdateLog);
ApplicationIo IO = new ApplicationIo(logCallback); //This is the line where the error gets flagged
"The best overloaded match for 'ApplicationIo(SWIGTYPE_p_f_PCWSTR__void)' has some invalid arguments."
This makes it seem to me like the CppCallback type in C# is not getting correctly mapped to the Callback type in C++, but I 'm not sure why this is happening. My .i file definitely uses those exact names in the call to %cs_callback.
Incidentally, I am very new to c++ (and fairly new to c# as well), so apologies if I am doing something really stupid!
Thanks very much for the help,
Jeremy
------------------------------------------------------------------------------ Live Security Virtual Conference Exclusive live event will cover all the ways today's security and threat landscape has changed and how IT managers can respond. Discussions will include endpoint security, mobile security and the latest in malware threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________ Swig-user mailing list Swig-user <at> lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/swig-user
RSS Feed