简体   繁体   中英

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. 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. As this is a very frequent scenario in C++ apparently I miss something trivial. 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

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

When I use the MyPoint class in C #:

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'

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?

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:

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"

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:

#!/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). I also added a quick test for MyTriangle in:

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 . You only need to do this inside modules that are imported, so in this instance MyPoint.i becomes:

%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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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