用多个C#.dll包装多个C++.dll

  • 本文关键字:dll C++ 包装 c# c++ swig
  • 更新时间 :
  • 英文 :


我正在做一个项目,用C#包装一个多dll C++SDK,试图用单独的C#dll包装每个原始C++dll。我遇到了一个问题,如果在C++库B和C中使用C++库A中的一些常见符号,就不可能进行包装。由于这是C++中非常常见的场景,显然我错过了一些琐碎的事情。花了几天的时间,我仍然不知所措,如果有任何帮助,我将不胜感激。

以下简单示例再现了该问题:-类点应该在库A中定义-类Triangle应该在使用A的库B中定义-类象限应该在使用的库C中定义

"MyPoint.h"
class  MyPoint
{
public:
MyPoint(double theX, double theY) : myX(theX), myY(theY) {}
double X() const { return myX; }
double& X() { return myX; }
double Y() const { return myY; }
double& Y() { return myY; }
private:
double myX;
double myY;
};
"MyTriangle.h"
#include "MyPoint.h"
class MyTriangle
{
public:
MyTriangle(const MyPoint& theP1, const MyPoint& theP2, const MyPoint& theP3) :
myP1(theP1),
myP2(theP2),
myP3(theP3) {}
MyPoint P1() const { return myP1; }
MyPoint& P1() { return myP1; }
MyPoint P2() const { return myP2; }
MyPoint& P2() { return myP2; }
MyPoint P3() const { return myP3; }
MyPoint& P3() { return myP3; }
private:
MyPoint myP1;
MyPoint myP2;
MyPoint myP3;
};
"MyQuadrangle.h"
#include "MyPoint.h"
class MyQuadrangle
{
public:
MyQuadrangle(const MyPoint& theP1, const MyPoint& theP2, const MyPoint& theP3, const MyPoint& theP4) :
myP1(theP1),
myP2(theP2),
myP3(theP3),
myP4(theP4) {}
MyPoint P1() const { return myP1; }
MyPoint& P1() { return myP1; }
MyPoint P2() const { return myP2; }
MyPoint& P2() { return myP2; }
MyPoint P3() const { return myP3; }
MyPoint& P3() { return myP3; }
MyPoint P4() const { return myP4; }
MyPoint& P4() { return myP4; }
private:
MyPoint myP1;
MyPoint myP2;
MyPoint myP3;
MyPoint myP4;
};

三角形和四边形分别由三个点和四个点组成。因此,这两个类(MyTriangle和MyQuadrangle)都使用类MyPoint。这三个类都是单独包装的。对于每个类都有它们的接口文件:

"MyPoint.i"
%module MyPointWrapper
%{
#include "MyPoint.h"
%}
%include <windows.i>
%include "MyPoint.h"
"MyTriangle.i"
%module MyTriangleWrapper
%{
#include "MyTriangle.h"
%}
%include "MyPoint.i"
%include "MyTriangle.h"
"MyQuadrangle.i"
%module MyQuadrangleWrapper
%{
#include "MyQuadrangle.h"
%}
%include "MyPoint.i"
%include "MyQuadrangle.h"

为每个文件编写了命令行界面:C: \swigwin-3.0.10.\swigwin3.0.10\swig-csharp-C++-namespace geometry-outdir C:\Geometrics\MyPointNet\Generated MyPoint.iC: \swigwin-3.0.10.\swigwin3.0.10\swig-csharp-C++-命名空间几何体-I"C:\Geometrics\MyPointcpp"-outdir C:\Geometrics \MyTriangleNet\Generated MyTriangle.IC: \swigwin-3.0.10.\swigwin3.0.10\swig-csharp-C++-命名空间几何体-I"C:\Geometrics\MyPointcpp"-outdir C:\Geometrics \MyQuadrangleNet\Generated MyQuadrangle.I

当我在C#中使用MyPoint类时:

using System;
using geometry;
namespace Example
{
class Program
{
static void Main(string[] args)
{
MyPoint P = new MyPoint (3, 4, 5);
}
}
}

出现一个错误,说明每个类都包含一种类型的MyPoint:类型"MyPoint"同时存在于"MyTriangleNet,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"中和'MyPointNet,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null'

如何避免这样的情况,但在C#中有三个完全功能的类,条件是每个类都将被单独包装?

您几乎已经做到了,但要简单地引用现有代码而不生成更多代码,您需要使用%import "modulename.i"而不是%include,因此您的.i文件变成:

MyPoint.i:

%module MyPointWrapper
%{
#include "MyPoint.h"
%}
%include "MyPoint.h"

MyQuadrangle.i:

%module MyQuadrangleWrapper
%{
#include "MyQuadrangle.h"
%}
%import "MyPoint.i"
%include "MyQuadrangle.h"

MyTriangle.i:

%module MyTriangleWrapper
%{
#include "MyTriangle.h"
%}
%import "MyPoint.i"
%include "MyTriangle.h"

无论如何,我都不是C#专家,所以我希望你必须使用%typemap(csimports)或其他东西来确保例如MyTriangle.cs知道如何引用它所指的MyPoint类型(使用非限定名称),但至少当我在Linux上用Mono测试它时,构建了一个似乎不需要的可执行文件:

#!/bin/bash
swig3.0 -csharp -c++ -namespace geometry -outdir MyPointNet MyPoint.i
swig3.0 -csharp -c++ -namespace geometry -outdir MyTriangleNet MyTriangle.i
swig3.0 -csharp -c++ -namespace geometry -outdir MyQuadrangleNet MyQuadrangle.i
g++ -Wall -Wextra -o libMyPointWrapper.so MyPoint_wrap.cxx -shared -fPIC
g++ -Wall -Wextra -o libMyQuadrangleWrapper.so MyQuadrangle_wrap.cxx -shared -fPIC
g++ -Wall -Wextra -o libMyTriangleWrapper.so MyTriangle_wrap.cxx -shared -fPIC
mcs run.cs */*.cs && ./run.exe

一旦我改变了你的示例用法,为MyPoint调用了一个存在的构造函数(2-arg),一切都正常了。我还在中添加了MyTriangle的快速测试

MyTriangle T = new MyTriangle(P,P,P);

此外,为了在多个程序集上实现这一点,您还需要做更多的工作,如文档中所述,将一些内部组件的可见性从internal更改为public。您只需要在导入的模块中执行此操作,因此在本例中,MyPoint.i变为:

%module MyPointWrapper
SWIG_CSBODY_PROXY(public, public, SWIGTYPE)
SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE)
%{
#include "MyPoint.h"
%}
%include "MyPoint.h"

请注意,文档提出了一些比公开更好的解决方案。如果这是我的生产代码,我会研究一下。

最新更新