我正在一个项目中,用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);


另外,要使此功能可跨多个程序集运行,您需要对internalpublic的某些内部零件进行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"


请注意,该文档提出了一些更好的解决方法,而不仅仅是公开发布。如果这是我的生产代码,我会调查一下。

09-20 03:57