2017-01-19 3 views
1

Я работаю над проектом для упаковки SDK с несколькими DLL с C#, пытаясь обернуть каждую исходную C++ dll отдельными C# -llll. Я столкнулся с проблемой, что если какой-то общий символ в C++-библиотеке A используется в библиотеке C++ C и C, его невозможно обернуть. Поскольку это очень частой сценарий в C++, я, по-видимому, пропускаю что-то тривиальное. Проведя несколько дней, я все еще теряю и буду признателен за любую помощь, как двигаться дальше.Обертка нескольких C++ .dlls с несколькими C# .dlls

Следующий простой пример воспроизводит проблему: - класс точки, как предполагается, должны быть определены в библиотеке - класс Triangle, как предполагается, должны быть определены в библиотеке B, которая использует - класс 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; 

}; 

Треугольник и четырехугольник установлены соответственно с тремя и четырьмя точками. Таким образом, оба класса (MyTriangle и MyQuadrangle) используют класс MyPoint. Все три класса обернута separately.For каждый из классов есть свой файл интерфейс:

"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

Когда я использую класс MyPoint в C#: появляется

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 = нейтральный, PublicKeyToken = null ' и' MyPointNet, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null '

Как избежать такой ситуации, но с тремя полностью функциональными классами на C#, на условие, что каждый из классов будет обернут отдельно?

+0

Я отбросил вопрос - сделанные вами изменения были ошибкой моего тестирования/ответа из-за отсутствия знаний C#/Windows, а не (очень хороших) деталей в вашем вопросе, и лучше, чтобы это было написано больше как запись в энциклопедии, чем сеанс интерактивной отладки. – Flexo

ответ

0

Вы почти получили его там, однако просто сослаться на существующий код без генерации больше вы должны использовать %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 который он ссылается, используя неквалифицированное имя, но, по крайней мере, когда я тестировал с Mono на Linux создания единого исполняемого файла, который не кажется, необходимы:

#!/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" 

Обратите внимание, что документация предполагает некоторые лучшие обходные пути, чем просто сделать его общедоступным. Если бы это был мой производственный код, я бы посмотрел на них.

+0

Большое спасибо за подсказку. После того, как я добавил модуль% в файл Triangle.i, я столкнулся с проблемой доступа к методам класса MyPoint из кода, сгенерированного для Triangle (тот же для Qudrangle). Оригинальное сообщение было отредактировано более подробно. – KKirill

+0

@KKrill, если вы запускаете SWIG с '-Wall', он довольно много предупреждает о том, что' internal' является зарезервированным словом в C#. Я предполагаю, что это связано с этим. – Flexo

+0

На самом деле, возможно, нет, кажется, что это некоторые модули C#, с которыми у меня нет опыта раньше. Будут копать еще немного. – Flexo