Proxying C#->C++ class wrappers using SWIG

2019-05-24 07:11发布

问题:

Say I have following C++ code:

/* File : example.h*/
typedef void (__stdcall *CppCallback)(int code, const char* message);

class CppClass
{
public:
    CppClass() {};
    void call(CppCallback callback)
    {
        callback(1234, "Hello from C++");
    }
};

And then I have C# counterpart:

/* File : example.cs */
using System;
using System.Text;

public delegate void CSharpCallback(int code, string param);

public class App
{
    static void Main()
    {
        CppClass cppClass = new CppClass();

        cppClass.call((i, s) => {
                Console.WriteLine("Code " + i + " and message '" + s + "'");
            });
    }
}

And then I have SWIG .i file gluing them together:

/* File : example.i */
%module example

%include <windows.i>
%include <stl.i>

%{
#include "example.h"
%}

%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(CppCallback, CSharpCallback)

%include "example.h"

Now, I want to proxy callback() in such a way that before C# lambda is executed it would do something, like print "Hooked". To make it possible I would need to also proxy CppClass.call() method so that it would save original callback/lambda/delegate parameter to call(), then define own handler (e.g. csharpCallback()) and feed it to P/Invoke corresponding to the callback. When C++ app calls callback() it will end up at my C# csharpCallback() which then will print "Hooked" and call the original saved callback, provided in C# cppClass.callback().

The question - can any SWIG experts suggest an elegant solution for generating this kind of hook wrappers?

回答1:

You should first decide how you would implement such a wrapper in pure C#. Then look at section 19.8.7 Extending proxy classes with additional C# code of the SWIG 2.0 docs. It might be a little tricky because you want to wrap the delegate, not the class. See how far you get and either update your question or post an answer!