How should I write the .i file to wrap callbacks in Java or C#

后端 未结 3 1398
孤独总比滥情好
孤独总比滥情好 2020-11-28 12:38

My C program uses callback functions which are periodically called. I want to be able to handle the callback functions in a Java or C# program. How should I write the .i fil

3条回答
  •  伪装坚强ぢ
    2020-11-28 12:50

    C++ to C# Callback Example

    This works nicely to allow C++ to execute callbacks to C#.

    Tested under:

    • C#: Visual Studio 2015
    • C++: Intel Parallel Studio 2017 SE
    • C++: Should work nicely for Visual Studio 2015 C++ (can anyone verify this?).
    • C++: Should work nicely for any other Windows C++ compiler that generates a standard .dll (can anyone verify this?).

    In your SWIG .i file, include this file callback.i:

    //////////////////////////////////////////////////////////////////////////
    // 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#.
    //
    // Tested under:
    // - C#: Visual Studio 2015
    // - C++: Intel Parallel Studio 2017 SE
    //
    // 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:
    //
    // C++: "callback.h":
    //    #pragma once
    //    typedef void(__stdcall *CppCallback)(int code, const char* message);
    //    void call(CppCallback callback);
    //
    // C++: "callback.cpp":
    //    #include "stdafx.h" // Only for precompiled headers.
    //    #include "callback.h"
    //    void call(CppCallback callback)
    //    {
    //        callback(1234, "Hello from C++");
    //    }
    //
    // C#: Add this manually to C# code (it will not be auto-generated by SWIG):
    //    public delegate void CSharpCallback(int code, string message);
    //
    // C#: Add this test method:
    //    public class CallbackNUnit
    //    {
    //        public void Callback_Test()
    //        {
    //            MyModule.call((code, message) =>
    //            {
    //                // Prints "Hello from C++ 1234"
    //                Console.WriteLine(code + " " + message);
    //            });   
    //        }        
    //    }
    //
    // SWIG: In your .i file:
    //   %module MyModule
    //   %{
    //     #include "callback.h"
    //   %}
    //   
    //   %include 
    //   %include 
    //   
    //   // Links typedef in C++ header file to manual delegate definition in C# file.
    //   %include "callback.i" // The right spot for this file to be included!
    //   %cs_callback(CppCallback, CSharpCallback)
    //   #include "callback.h"
    //
    // 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. 
    //
    // References: 
    // - http://swig.10945.n7.nabble.com/C-Callback-Function-Implementation-td10853.html
    // - http://stackoverflow.com/questions/23131583/proxying-c-c-class-wrappers-using-swig             
    //
    // Typemap for callbacks:
    %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
      
    

提交回复
热议问题