简体   繁体   English

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

[英]Wrapping multiple C++ .dlls with multiple C# .dlls

I am working on a project to wrap a multi-dll C++ SDK with C# trying to wrap each original C++ dll with separate C# dlls. 我正在开发一个项目,用C#包装一个多dll C ++ SDK,尝试用独立的C#dll包装每个原始的C ++ dll。 I encountered an issue that if some common symbol in C++ library A is used in C++ library B and C, it is impossible to wrap. 我遇到了一个问题,如果在C ++库B和C中使用C ++库A中的某些常用符号,则无法进行换行。 As this is a very frequent scenario in C++ apparently I miss something trivial. 因为在C ++中这是一个非常频繁的场景,显然我想念一些微不足道的东西。 Having spent a few days I am still at loss and would appreciate any help how to move on. 花了几天我仍然感到茫然,并感谢任何帮助如何继续前进。

The following simple sample reproduces the problem: - class Point is supposed to be defined in library A - class Triangle is supposed to be defined in library B which uses A - class Quadrange is supposed to be defined in library C which uses A 下面的简单示例再现了这个问题: - 类Point应该在库A中定义 - 类Triangle应该在库B中定义,它使用A类Quadrange应该在库C中定义,它使用A

"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;

};

The triangle and the quadrangle are set respectively with three and four points. 三角形和四边形分别设置有三个和四个点。 Thus, both of the classes (MyTriangle and MyQuadrangle) use class MyPoint. 因此,两个类(MyTriangle和MyQuadrangle)都使用MyPoint类。 All three classes are wrapped separately.For each of the classes have their interface file: 所有三个类都是单独包装的。每个类都有自己的接口文件:

"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"

The command line interface was written for each file: C:\\swigwin-3.0.10\\swigwin-3.0.10\\swig -csharp -c++ -namespace geometry -outdir C:\\Geometrics\\MyPointNet\\Generated MyPoint.i C:\\swigwin-3.0.10\\swigwin-3.0.10\\swig -csharp -c++ -namespace geometry -I"C:\\Geometrics\\MyPointcpp" -outdir C:\\Geometrics\\MyTriangleNet\\Generated MyTriangle.i C:\\swigwin-3.0.10\\swigwin-3.0.10\\swig -csharp -c++ -namespace geometry -I"C:\\Geometrics\\MyPointcpp" -outdir C:\\Geometrics\\MyQuadrangleNet\\Generated MyQuadrangle.i 为每个文件编写了命令行界面:C:\\ swigwin-3.0.10 \\ swigwin-3.0.10 \\ swig -csharp -c ++ -namespace geometry -outdir C:\\ Geometrics \\ MyPointNet \\ Generated MyPoint.i C:\\ swigwin -3.0.10 \\ swigwin-3.0.10 \\ swig -csharp -c ++ -namespace geometry -I“C:\\ Geometrics \\ MyPointcpp”-outdir C:\\ Geometrics \\ MyTriangleNet \\ Generated MyTriangle.i C:\\ swigwin-3.0.10 \\ swigwin-3.0.10 \\ swig -csharp -c ++ -namespace geometry -I“C:\\ Geometrics \\ MyPointcpp”-outdir C:\\ Geometrics \\ MyQuadrangleNet \\ Generated MyQuadrangle.i

When I use the MyPoint class in C #: 当我在C#中使用MyPoint类时:

using System;
using geometry;

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

an error appears that says that each class contains a type of MyPoint: The type 'MyPoint' exists in both 'MyTriangleNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'MyPointNet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 出现一个错误,表示每个类都包含一个MyPoint类型:'MyTriangleNet,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'和'MyPointNet,Version = 1.0.0.0,Culture =中性,PublicKeyToken = null'

How to avoid such a situation, but having three fully functional classes in C #, on the condition that each of the classes will be wrapped separately? 如何避免这种情况,但在C#中有三个功能齐全的类,条件是每个类将被单独包装?

You've almost got it there, however to simply refer to existing code without generating more you need to use %import "modulename.i" instead of %include , so your .i files become: 您几乎已经实现了它,但是为了简单地引用现有代码而不产生更多,您需要使用%import "modulename.i"而不是%include ,因此您的.i文件变为:

MyPoint.i: MyPoint.i:

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

MyQuadrangle.i: MyQuadrangle.i:

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

MyTriangle.i: MyTriangle.i:

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

I'm not a C# expert by any means, so I was expecting that you'd have to use %typemap(csimports) or something else to make sure that eg MyTriangle.cs knew how to reference the MyPoint type which it refers to using an unqualified name, but at least when I tested it with Mono on Linux building a single executable that didn't seem to be needed: 我无论如何都不是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

All worked correctly once I'd changed your example usage to call a constructor for MyPoint that existed (2-arg). 一旦我改变你的示例用法来调用MyPoint的构造函数(2-arg),一切正常。 I also added a quick test for MyTriangle in: 我还为MyTriangle添加了一个快速测试:

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

Additionally to make this work across multiple assemblies you'll need to do a little more work, as outlined in the documentation, to change the visibility of some of the internals from internal to public . 此外,为了使这项功能适用于多个程序集,您需要执行更多工作(如文档中所述),以更改某些内部组件从internalpublic的可见性。 You only need to do this inside modules that are imported, so in this instance MyPoint.i becomes: 您只需要在导入的模块中执行此操作,因此在此实例中MyPoint.i变为:

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

Note that the documentation suggests some better workarounds than just making it public. 请注意,文档提供了一些更好的解决方法,而不仅仅是公开它。 If it were my production code I'd look into those. 如果是我的生产代码,我会调查那些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM