Swig C++ to C#:如何从 C++ 包装类以使模板类中的方法在 C# 的派生类中可用?

Posted

技术标签:

【中文标题】Swig C++ to C#:如何从 C++ 包装类以使模板类中的方法在 C# 的派生类中可用?【英文标题】:Swig C++ to C#: How to wrap classes from C++ to make methods from template class available in derived class in C#? 【发布时间】:2017-01-12 07:34:40 【问题描述】:

我在命名空间 external::internal 中有模板类 BaseMyPoint

它实现了公共方法 X()、Y()、Z() 和 SetCoord()。

然后写

typedef internal::BaseMyPoint MyPointd;

创建派生类 MyPoint,它使用 public 继承 MyPointd

两个类的描述都存储在文件“myPoint.h”中:

#pragma once

#ifdef MYPOINTSDLL_EXPORTS
#define MYPOINTSDLL_API __declspec(dllexport) 
#else
#define MYPOINTSDLL_API __declspec(dllimport) 
#endif

namespace external 

namespace internal 

    template<typename T>
    struct MyPointTraits;

    template<>
    struct MyPointTraits<double>
    
        typedef double  ValueType;
        static ValueType CoincidenceTolerance()  return 1e-7; 
    ;

    template<>
    struct MyPointTraits<float>
    
        typedef float  ValueType;
        static ValueType CoincidenceTolerance()  return 1e-7f; 
    ;

    template<typename T>
    class BaseMyPoint
    
    public:

        T myX;
        T myY;
        T myZ;

        typedef typename MyPointTraits<T>::ValueType    ValueType;

        BaseMyPoint() 

        BaseMyPoint(ValueType theX, ValueType theY, ValueType theZ) :
            myX(theX), myY(theY), myZ(theZ) 

        BaseMyPoint(const BaseMyPoint& theOther) :
            myX(theOther.myX), myY(theOther.myY), myZ(theOther.myZ) 

        ValueType X() const  return myX; 
        ValueType& X()  return myX; 

        ValueType Y() const  return myY; 
        ValueType& Y()  return myY; 

        ValueType Z() const  return myZ; 
        ValueType& Z()  return myZ; 

        void SetCoord(ValueType theX, ValueType theY, ValueType theZ)
        
            X() = theX;
            Y() = theY;
            Z() = theZ;
        
    ;



typedef internal::BaseMyPoint<double>   MyPointd;

typedef internal::BaseMyPoint<float>    MyPointf;

class MyPoint : public MyPointd

public:

    MyPoint() 

    MyPoint(const MyPointd& theOther) : MyPointd(theOther) 
;


写入接口文件“myPoint.i”:

%module myPointsWrapper

%
#include "myPoint.h"
using namespace external;
using namespace external::internal;
%

%include <windows.i>
%include "myPoint.h"

在命令行中我写: C:\swig -csharp -c++ -namespace pointspase -outdir C:\myPoints\myPointcs\Generated myPoint.i

在 C# 中,我们通过实例 MyPoint aPoint 引用这些方法(X()、Y()、Z()、SetCoord()):

using System;
using pointspase;

namespace myPointcs

        class Program
        
            static void Main(string[] args)
            
                    MyPoint aPoint = new MyPoint();

                    double x = 0.2, y = 0.3, z = 0.4;
                    aPoint.SetCoord(x, y, z);

                    double X = aPoint.X(), Y = aPoint.Y(), Z = aPoint.Z();
            
        
    

我有

错误 CS1061 'MyPoint' 不包含 'Z' 的定义并且没有扩展方法 'Z' 接受第一个 可以找到“MyPoint”类型的参数(您是否缺少 using 指令或程序集引用?)

错误 CS1061 'MyPoint' 不包含 'Y' 的定义并且没有扩展方法 'Y' 接受第一个 可以找到“MyPoint”类型的参数(您是否缺少 using 指令或程序集引用?)

错误 CS1061 'MyPoint' 不包含 'X' 的定义并且没有扩展方法 'X' 接受第一个 可以找到“MyPoint”类型的参数(您是否缺少 using 指令或程序集引用?)

错误 CS1061 'MyPoint' 不包含 'SetCoord' 的定义并且没有扩展方法 'SetCoord' 可以找到接受“MyPoint”类型的第一个参数(您是否缺少 using 指令或程序集引用?)

如何使这些方法在 C# 类 MyPoint 中可用?

提前感谢您的关注, 基里尔

编辑 1

这是一个简单的例子,清楚地表达了我的问题。

我在“file.h”中写

template <typename T>
class myclass 
public:
    T get() const  return 0; 
;

class myintclass : public myclass<int> ;

我在“file.i”中写

%template (myclassi) myclass<int>

当我编译接口文件时出现警告:

warning 401: Base class 'myclass< int >' undefined.
warning 401: 'myclass< int >' must be defined before it is used as a base class. 

因此,C# 类 myintclass 不包含方法 get()。 如何更改接口文件以使 myintclass 类中的 get() 方法可用?

【问题讨论】:

请参阅 SWIG 文档中的 %template。您必须实例化您想要支持的模板实例。 非常感谢您提供提示。在我将 %template 添加到 MyPoint.i 文件后,我遇到了同样的问题。原帖已编辑。我添加了一个简单的例子,清楚地表达了我的问题。 在您的简单示例中,这是 .i 文件中的唯一行吗?您仍然需要拥有%module%include "file.h"。另请参阅***.com/a/16269493/235698。 【参考方案1】:

鉴于您编辑中的file.h,正确声明所有内容有点棘手。理想情况下,模板应位于与myintclass 定义不同的标头中,但这是一种经过测试的方法:

文件.i

%module test

%
#include "file.h"
%

// Process the template first
template <typename T>
class myclass 
public:
    T get() const  return 0; 
;

// Tell SWIG to generate code for a template instance.

%template(myclassi) myclass<int>;

// Now that SWIG has code for the template instance,
// SWIG can generate code for classes using the template instance.
class myintclass : public myclass<int> ;

测试模块(我为 Python 生成):

>>> import test
>>> t=test.myclassi()
>>> t.get()
0
>>> t=test.myintclass()
>>> t.get()
0

【讨论】:

以上是关于Swig C++ to C#:如何从 C++ 包装类以使模板类中的方法在 C# 的派生类中可用?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SWIG,如何将 C++ void func(Class& out) 包装为 C# Class func()?

swig c++ to perl : 如何使用 c++11 字符串 STL 函数

如何将 C# 字符串 [] 编组(理想情况下在 SWIG 中)到 C++ 字符串*?

SWIG C++ to Python:生成 Python 列表的子类

Swig 包装一个 C++ 数据类型?

使用 SWIG 包装对象从 C++ 调用 Python 函数的最简洁方法是啥