用多个 C# .dll 包装多个 C++ .dll
Posted
技术标签:
【中文标题】用多个 C# .dll 包装多个 C++ .dll【英文标题】:Wrapping multiple C++ .dlls with multiple C# .dlls 【发布时间】:2017-01-19 14:41:30 【问题描述】:我正在开发一个项目,用 C# 包装多 dll C++ SDK,试图用单独的 C# dll 包装每个原始 C++ dll。我遇到了一个问题,如果 C++ 库 A 中的一些常用符号在 C++ 库 B 和 C 中使用,则无法换行。由于这是 C++ 中非常常见的场景,显然我错过了一些琐碎的事情。花了几天时间后,我仍然不知所措,如果能帮助我继续前进,我将不胜感激。
以下简单示例重现了该问题: - 类 Point 应该在库 A 中定义 - 类 Triangle 应该在使用 A 的库 B 中定义 - Quadrange 类应该在使用 A 的库 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\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++ -命名空间几何 -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# 中使用 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# 中拥有三个功能齐全的类,条件是每个类都将单独包装?
【问题讨论】:
我回滚了这个问题 - 由于缺乏 C#/Windows 知识,您所做的编辑是我的测试/答案的错误,而不是您问题中的(非常好的)细节,最好把它写得更像百科全书条目而不是交互式调试会话。 【参考方案1】:您几乎已经完成了,但是要简单地引用现有代码而不生成更多代码,您需要使用 %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);
此外,要跨多个程序集进行这项工作,您还需要在a little more work, as outlined in the documentation, to change 中查看从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"
请注意,文档提出了一些比仅仅公开它更好的解决方法。如果是我的生产代码,我会调查这些。
【讨论】:
非常感谢您提供提示。在我将 %module 添加到 Triangle.i 文件后,我遇到了从为 Triangle 生成的代码(与 Qudrangle 相同)中访问 MyPoint 类的方法的问题。对原始帖子进行了更详细的编辑。 @KKrill 如果您使用-Wall
运行SWIG,它会警告很多关于internal
是C# 中的保留字。我的猜测是与此有关。
实际上可能不是,似乎这是我以前没有经验的一些 C# 模块。会再挖一点。
知道了。即将进行一项编辑。事实证明,这正是我在使用 Mono 编译之前提到的问题,但文档中已经有了更简洁的解决方案。
非常感谢您的详细解答。它帮助我解决了我的问题!以上是关于用多个 C# .dll 包装多个 C++ .dll的主要内容,如果未能解决你的问题,请参考以下文章