Когда вы расширяете класс с помощью %extend
, вы не можете добавить новые переменные-члены, а только функции-члены. Он предположит существование функции get/set, если вы сделаете это в %extend
.
Причина в том, что память (то есть память) для новых переменных-членов должна была бы где-то жить, но нет очевидного безопасного места для ее размещения. Вы не можете изменить исходный C++ class
, потому что если вы это сделаете, вы получите неопределенное поведение, когда какой-либо другой, предварительно скомпилированный код использует старое определение класса; нет никакого способа ретроспективно применить новое определение. Вы не можете поместить его в прокси-сервер, который генерируется на целевом языке, потому что не существует сопоставления 1: 1 между экземплярами классов C++ и прокси-серверов на целевом языке. (Рассмотрим две функции, которые возвращают один и тот же глобальный экземпляр через указатель для тривиального примера того, как это может произойти).
Если вы хотите реализовать функции get/set, чтобы сделать что-то полезное (например, здесь я использовал глобальную карту для хранения дополнительных данных), которую вы не хотите реализовывать внутри %extend
Например, данный test.hh с просто:
template <typename T>
struct Foo {};
вы можете использовать std::map
делать то, что вы пытаетесь сделать, написав свой собственный получает и устанавливает как свободные функции в обертке - %{ %}
просто передает код прямо через:
%module test
%include "test.hh"
%{
#include "test.hh"
%}
%{
#include <map>
static std::map<Foo<int>*, double> extra_stuff;
const double& Foo_Sl_int_Sg__x_get(Foo<int>* f) {
return extra_stuff[f];
}
void Foo_Sl_int_Sg__x_set(Foo<int>* f, const double& d) {
extra_stuff[f] = d;
}
%}
%template(FooInt) Foo<int>;
%extend Foo<int> {
double x;
}
GE t/set функции искажаются собственной системой управления SWIG, потому что это шаблон. Я просто посмотрел в сгенерированный класс-оболочку, чтобы узнать, что они вызвали. (Я думаю, что может быть более умный способ сделать это, но я не мог понять это из документации). Если бы это был не шаблон, имя функций было бы намного проще.
Обратите внимание, что здесь нет никаких положений, позволяющих удалять записи с этой карты - он будет просто расти бесконечно. (Вы можете обойти это, например, путем предоставления типовой карты, которая вызывает дополнительную функцию в конце жизни объекта). Вы также должны быть осторожны в отношении потоков.
Поскольку вы не указали, какой язык вы используете я тестировал выше кода Java:
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
FooInt f = new FooInt();
f.setX(0.1);
System.out.println(f.getX());
}
}
В качестве альтернативы, если вы действительно хотите, то можете написать код, чтобы убедиться, что существует единственный экземпляр одного прокси на целевом языке, написав типовую карту, которая проверяет, создан ли прокси-сервер вместо того, чтобы всегда создавать его, но это вызывает проблемы с подсчетом ссылок и безопасностью потоков, которые трудно решать эффективно и в целом, поэтому он не является стандартным поведение.
Простейшим обходным решением во многих случаях (например, итераторами на целевом языке) является использование %inline
, чтобы объявить и определить и полностью обернуть все совершенно новый дополнительный класс, который обеспечивает требуемые функции.
Не связано с моим ответом, но является ли 'myclass * f' означающим« указатель »здесь? Вам не нужно явно писать этот аргумент, но вам нужно использовать '$ self' вместо' this' с '% extend'. – Flexo
Да, это, по сути, то, как я пытался его использовать. Я решил, что этот формат был альтернативой использованию «$ self» вместо «this». Возможно, я не могу этого сделать. – thebigdog