Для класса без шаблона я бы написал что-то вроде этого
Но я не знаю, что мне делать, если мой класс является классом шаблона.
Я пробовал что-то вроде этого, и он не работает.
extern "C" {
Demodulator<double>* Foo_new_double(){ return new Demodulator<double>(); }
Demodulator<float>* Foo_new_float(){ return new Demodulator<float>(); }
void demodulateDoubleMatrix(Demodulator<double>* demodulator, double * input, int rows, int columns){ demodulator->demodulateMatrixPy(input, rows, columns) }
}
Примечание. Ваш вопрос частично противоречит коду, поэтому я сейчас игнорирую код.
Шаблоны C++ - это разработанный макрокоманд, который разрешается во время компиляции. Другими словами, двоичный код содержит только код из экземпляров шаблонов (это то, что вы получаете, когда вы применяете параметры, типично типы, к шаблону), и это все, что вы можете экспортировать из двоичного кода на другие языки. Экспорт их похож на экспорт любого обычного типа, например, std::string
.
Поскольку сами шаблоны не выдерживают компиляцию, вы не можете экспортировать их из двоичного, а не из C, а не в Python, даже в C++! Для последнего вы можете предоставить сами шаблоны, но это не включает их в двоичный файл.
Два предположения:
Язык C++ запущен как надмножество C: То есть он содержит новые ключевые слова, синтаксис и возможности, которые C не предоставляет. C не имеет понятия class
, не имеет понятия функции-члена и не поддерживает понятие ограничений доступа. C также не поддерживает наследование. Однако действительно большая разница - это шаблоны. C имеет макросы и что это.
Поэтому нет, вы не можете напрямую разоблачить код C++ на C любым способом, вам придется использовать код C-стиля в вашем C++, чтобы открыть слой C++.
template<T> T foo(T i) { /* ... */ }
extern "C" int fooInt(int i) { return foo(i); }
Однако C++ изначально был генератором кода C, а C++ все еще может взаимодействовать (с одной стороны) с C ABI: функции-члены фактически реализуются путем поворота функции this->function(int arg);
в ThisClass0int1(this, arg);
или что-то типа того. В теории вы могли бы написать что-то, чтобы сделать это с вашим кодом, возможно, используя clang.
Но это нетривиальная задача, которая уже хорошо справляется с SWIG, Boost :: Python и Cython.
Однако проблема с шаблонами заключается в том, что компилятор игнорирует их до тех пор, пока вы не будете "создавать" (использовать) их. std :: vector <> не является конкретной вещью, пока вы не укажете std::vector<int>
или что-то еще. И теперь единственной конкретной реализацией этого является std::vector<int>
. Пока вы не указали его где-нибудь, std::vector<string>
не существует в вашем двоичном файле.
Вероятно, вы хотите начать с того, что посмотрите на что-то вроде этого http://kos.gd/2013/01/5-ways-to-use-python-with-native-code/, выберите инструмент, например SWIG, а затем запустите создавая интерфейс, чтобы выявить то, что вам нужно/нужно C. Это намного меньше, чем создание самих оберток. В зависимости от того, какой инструмент вы используете, это может быть так же просто, как написание строки using std::vector<int>
или typedef std::vector<int> IntVector
или что-то в этом роде.
---- РЕДАКТИРОВАТЬ ----
Проблема с классом шаблона заключается в том, что вы создаете цельный тип, который C не может понять, рассмотрите:
template<typename T>
class Foo {
T a;
int b;
T c;
public:
Foo(T a_) : a(a_) {}
void DoThing();
T GetA() { return a; }
int GetB() { return b; }
T GetC() { return c; }
};
Язык C не поддерживает ключевое слово class
, не важно понимать, что члены a, b и c являются частными или конструкторами, а C не понимает функции-члены.
Опять же, он не понимает шаблоны, поэтому вам нужно будет сделать то, что C++ делает автоматически, и создать экземпляр вручную:
struct FooDouble {
double a;
int b;
double c;
};
Кроме того, все эти переменные являются частными. Так вы действительно хотите разоблачить их? Если нет, вам, вероятно, просто нужно ввести typedef "FooDouble" к тому же размеру, что и Foo, и сделать макрос для этого.
Затем вам нужно написать замены для функций-членов. C не понимает конструкторы, поэтому вам нужно будет написать
extern "C" FooDouble* FooDouble_construct(double a);
FooDouble* FooDouble_construct(double a) {
Foo* foo = new Foo(a);
return reinterept_cast<FooDouble*>(foo);
}
и деструктор
extern "C" void FooDouble_destruct(FooDouble* foo);
void FooDouble_destruct(FooDouble* foo) {
delete reinterpret_cast<Foo*>(foo);
}
и аналогичный проход для аксессуаров.
extern "C" ...
вы даете обещание компилятору, что все в elipsis будет кодом C
и, опять же, C не имеет шаблонов.
extern "C"