首页 > 编程语言 >使用swig映射c++function

使用swig映射c++function

时间:2024-09-20 16:50:47浏览次数:1  
标签:function __ Name ## swig c++ std action

swig可以自动生成从c++到其他语言如Java、Python等转换的中间语言,目前swig已经支持很多c++11的特性了,但是这次项目中发现function特性还没有支持,只能自己生成。

从网上找了一份Java的java - How to use SWIG to wrap std::function objects? - Stack Overflow,我需要的c#的,故需要稍微修改一下。

主要思想是为std::function生成结构体,这样结构体的operator()函数就可以映射到c#中作为回调函数,要注意的是operator()函数要是虚函数,c#那边才能重写。

其他部分还有:1.利用宏和__VA_ARGS__实现自定义多个参数;2.使用抽象类和代理类避免c#function自动gc。

至于用法就很简单了,比如%define %std_function(my_fuc, int, int),c#那边就继承my_fuc类,并重写my_fucDelegate函数,然后将对象传给c++即可。

而我的项目中并不止调用fuc,还要存储并可能查找和删除,但是如果使用对象的话,很次从c#传到c++时在swig层会重新new一个c++对象,导致无法根据对象查找到之前的,因此最后选择的是存储对象指针,c++和c#共用一份指针,由c#生成和自动释放。

  1 %{
  2   #include <functional>
  3   #include <iostream>
  4 
  5   #ifndef SWIG_DIRECTORS
  6   #error "Directors must be enabled in your SWIG module for std_function.i to work correctly"
  7   #endif
  8 %}
  9 
 10 // These are the things we actually use
 11 #define param(num,type) $typemap(cstype,type) arg ## num
 12 #define unpack(num,type) arg##num
 13 #define lvalref(num,type) type arg##num
 14 #define forward(num,type) std::forward<type>(arg##num)
 15 
 16 // This is the mechanics
 17 #define FE_0(...)
 18 #define FE_1(action,a1) action(0,a1)
 19 #define FE_2(action,a1,a2) action(0,a1), action(1,a2)
 20 #define FE_3(action,a1,a2,a3) action(0,a1), action(1,a2), action(2,a3)
 21 #define FE_4(action,a1,a2,a3,a4) action(0,a1), action(1,a2), action(2,a3), action(3,a4)
 22 #define FE_5(action,a1,a2,a3,a4,a5) action(0,a1), action(1,a2), action(2,a3), action(3,a4), action(4,a5)
 23 
 24 #define GET_MACRO(_1,_2,_3,_4,_5,NAME,...) NAME
 25 #define tostring(x) #x
 26 
 27 %define FOR_EACH(action,...) 
 28   GET_MACRO(__VA_ARGS__, FE_5, FE_4, FE_3, FE_2, FE_1, FE_0)(action,__VA_ARGS__)
 29 %enddef
 30 
 31 
 32 %define %std_function(Name, Ret, ...)
 33 
 34 %feature("director") Name##Impl;
 35 %typemap(csclassmodifiers) Name##Impl "public abstract class";
 36 
 37 %{
 38   struct Name##Impl {
 39     virtual ~Name##Impl() {}
 40     virtual Ret Name##Delegate(__VA_ARGS__) = 0;
 41   };
 42 %}
 43 
 44 %csmethodmodifiers Name##Impl::Name##Delegate "abstract protected";
 45 %typemap(csout) Ret Name##Impl::Name##Delegate ";" // Suppress the body of the abstract method
 46 
 47 struct Name##Impl {
 48   virtual ~Name##Impl();
 49 protected:
 50   virtual Ret Name##Delegate(__VA_ARGS__) = 0;
 51 };
 52 
 53 %typemap(maybereturn) SWIGTYPE "return ";
 54 %typemap(maybereturn) void "";
 55 
 56 %typemap(csin) std::function<Ret(__VA_ARGS__)>& "$csclassname.getCPtr($csclassname.makeNative($csinput))"
 57 %typemap(csin) std::function<Ret(__VA_ARGS__)> "$csclassname.getCPtr($csclassname.makeNative($csinput))"
 58 %typemap(csin) std::function<Ret(__VA_ARGS__)> * "$csclassname.getCPtr($csclassname.makeNative($csinput))"
 59 
 60 %typemap(cscode) std::function<Ret(__VA_ARGS__)> %{
 61   public class Name##Impl##Cb: Name##Impl
 62   {
 63     protected override $typemap(cstype, Ret) Name##Delegate(FOR_EACH(param, __VA_ARGS__)){
 64       $typemap(maybereturn, Ret)m_cb.Name##Delegate(FOR_EACH(unpack, __VA_ARGS__));
 65     }
 66 
 67     public void Set##Name(Name cb){
 68       m_cb = cb;
 69     }
 70 
 71     private Name m_cb;
 72   }
 73 
 74   protected Name() {
 75     wrapper = new Name##Impl##Cb();
 76     Name##Impl##Cb tmpwrapper = wrapper as Name##Impl##Cb;
 77     tmpwrapper.Set##Name(this);
 78     proxy = new $csclassname(wrapper);
 79   }
 80 
 81   static public $csclassname makeNative($csclassname varin) {
 82     if (null == varin.wrapper) return varin;
 83     return varin.proxy;
 84   }
 85 
 86   // Bot of these are retained to prevent garbage collection from happenign to early
 87   private Name##Impl wrapper;
 88   private $csclassname proxy;
 89 %}
 90 
 91 %rename(Name) std::function<Ret(__VA_ARGS__)>;
 92 %rename(Name##Delegate) std::function<Ret(__VA_ARGS__)>::operator();
 93 
 94 namespace std {
 95   struct function<Ret(__VA_ARGS__)> {
 96     // Copy constructor
 97     function<Ret(__VA_ARGS__)>(const std::function<Ret(__VA_ARGS__)>&);
 98 
 99     // Name##Delegate operator 
100     virtual Ret operator()(__VA_ARGS__) const;
101 
102     // Conversion constructor from function pointer
103     function<Ret(__VA_ARGS__)>(Ret(*const)(__VA_ARGS__));
104 
105     %extend {
106       function<Ret(__VA_ARGS__)>(Name##Impl *varin) {
107     return new std::function<Ret(__VA_ARGS__)>([=](FOR_EACH(lvalref,__VA_ARGS__)){
108           return varin->Name##Delegate(FOR_EACH(unpack,__VA_ARGS__));
109     });
110       }
111     }
112   };
113 }
114 
115 %enddef

标签:function,__,Name,##,swig,c++,std,action
From: https://www.cnblogs.com/qinhq16/p/18422780

相关文章

  • C++ | 多态
     前言本篇博客讲解c++中的继承......
  • 【C++二叉树】105.从前序与中序遍历序列构造二叉树
    105.从前序与中序遍历序列构造二叉树-力扣(LeetCode)根据前序遍历和中序遍历构建二叉树前序遍历访问方式:根-左子树-右子树中序遍历访问方式:左子树-根-右子树思路分析:前序+中序可以构建一颗二叉树:前序遍历可以确定根,中序遍历可以确定左子树的中序区间和右子树的中序区......
  • 帝国CMS报错Deprecated: Function get_magic_quotes
    当使用帝国CMS时遇到“Deprecated:Functionget_magic_quotes”这类报错,通常是因为PHP版本升级后,某些旧的函数被弃用。get_magic_quotes_gpc() 函数在PHP5.4中已被弃用,并在PHP7.0中被移除。原因分析PHP版本升级:如果你的服务器从较旧的PHP版本(如5.3或更低)升级到了PHP7.......
  • C++异常
    1.C语言传统的处理错误的方式传统的错误处理机制:1.终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。2.返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误实际中C语言基本都是使用......
  • C++11
    1.C++11简介在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。......
  • 兼收并蓄 TypeScript - 类: function
    源码https://github.com/webabcd/TypeScriptDemo作者webabcd兼收并蓄TypeScript-类:function示例如下:class\function.ts{//定义函数时要指定参数的类型和返回值的类型,无返回值时可以用void表示functionf1(x:number,y:number):number{retur......
  • C++模版
    文章目录一、函数模版1、模版的语法2、多个模版类型参数3、模版的实力化二、类模版1、using2、类模版解决问题一、函数模版1、模版的语法模版的关键字为template,后面跟<>尖括号,尖括号里面填类型,类型前面跟一个关键字typename,也可以用class模版生成的函数就......
  • C++类与对象(三)
    目录1.再谈构造函数1.1构造函数体赋值1.2初始化列表1.3explicit关键字2.STATIC成员2.1概念2.2特性3.C++中成员初始化的新玩法4.友元4.1友元函数4.2友元类5.内部类6.再次理解封装7.再次理解面向对象本次内容大纲:1.再谈构造函数1.1构造函数体赋值在......
  • C++扫盲--直接构造(Direct Initialization)
      在C++中,直接构造(DirectInitialization)是由一种对象构造的方式,它直接调用类的构造函数来初始化对象。这种方式通常用于创建对象时立即提供必要的参数。直接构造的语法如下:ClassNameobjectName(arguments);其中,ClassName是类的名称,objectName是要创建的对象的名称,argument......
  • C++20 模块化(Modules)
    C++20引入的模块化(Modules)是一个重大改进,旨在取代传统的头文件机制,提高编译速度、代码可维护性以及项目的可扩展性。模块化为C++提供了一种更现代化的代码组织方式,避免了头文件中常见的宏污染、重复编译和复杂的依赖管理问题。概念与背景在C++20之前,C++项目是通过头文......