我正在一个项目中,用C#包装一个多DLL C ++ SDK,试图用单独的C#dll包装每个原始C ++ dll。我遇到了一个问题,如果C ++库B和C中使用了C ++库A中的某些常见符号,则无法包装。因为这是C ++中非常常见的情况,所以显然我错过了一些琐碎的事情。花了几天的时间我仍然很茫然,不胜感激继续前进。
下面的简单示例重现该问题:
-类Point应该在库A中定义
-应该在使用A的库B中定义类Triangle
-应该在使用A的库C中定义Quadrange类
"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 \ swigwin-3.0.10 \ swig -csharp -c ++-命名空间几何-outdir C:\ Geometrics \ MyPointNet \ Generated MyPoint.i
C:\ swigwin-3.0.10 \ swigwin-3.0.10 \ swig -csharp -c ++-命名空间几何-I“ C:\ Geometrics \ MyPointcpp” -outdir C:\ Geometrics \ MyTriangleNet \ Generated MyTriangle.i
C:\ swigwin-3.0.10 \ swigwin-3.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,版本= 1.0.0.0,区域性=中性,PublicKeyToken =空”中
和“ MyPointNet,版本= 1.0.0.0,区域性=中性,PublicKeyToken =空”
如何避免这种情况,但是在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
的某些内部零件进行a little more work, as outlined in the documentation, to change可见性。您只需要在导入的模块中执行此操作,因此在这种情况下,MyPoint.i变为:%module MyPointWrapper
SWIG_CSBODY_PROXY(public, public, SWIGTYPE)
SWIG_CSBODY_TYPEWRAPPER(public, public, public, SWIGTYPE)
%{
#include "MyPoint.h"
%}
%include "MyPoint.h"
请注意,该文档提出了一些更好的解决方法,而不仅仅是公开发布。如果这是我的生产代码,我会调查一下。