У меня есть следующие три файла:
sab1.hpp:
class CRectangle
{
int x, y;
public:
void set_values (int,int);
void print(char **db);
int area ();
};
sab1.cpp:
#include <iostream>
#include "sab1.hpp"using namespace std;
int CRectangle::area ()
{
return (x*y);
}
void CRectangle::set_values (int a, int b)
{
x = a;
y = b;
}
void CRectangle::print(char **db)
{
cout <<db[0];
}
int main ()
{
CRectangle rect;
char *a[] = {"Hi", "bye" } ;
rect.set_values (3,4);
cout << "area: " << rect.area();
rect.print(&a[0]);
return 0;
}
sab1.i:
%module Rec
%{
/* Includes the header in the wrapper code */
#include "sab1.hpp"%}
class CRectangle {
int x, y;
public:
void set_values (int,int);
void print(char **db);
int area ();
};
Я создаю различные промежуточные файлы, используя следующие обычные команды:
1) swig -c ++ -java sab1.i
2) g ++ -fpic -c sab1.cpp sab1_wrap.cxx -I / usr / lib / jvm / java-6-openjdk-i386 / include / -I / usr / lib / jvm / java-6-openjdk-i386 / include / Linux /
Затем я создаю разделяемую библиотеку, используя это: g ++ —shared sab1.o sab1_wrap.o -o libegs.so
Затем я создаю следующий Java-файл для доступа к функциям класса C ++:
public class Test
{
public static void main(String args[])
{
System.loadLibrary("egs");
CRectangle a = new CRectangle();
a.set_values(4,5);
System.out.println(a.area());
a.print("Hi");
}
}
Когда я компилирую файл Java (javac -classpath. Test.java), я получаю следующую ошибку:
Test.java:17: print(SWIGTYPE_p_p_char) in CRectangle cannot be applied to (java.lang.String) a.print("Hi");
^
Итак, как я могу заставить Java-код понимать переменную char **? Я попытался создать набор шрифтов в файле интерфейса SWIG (sab1.i), но я не могу правильно это выяснить.
Заранее спасибо за помощь.
%module Rec
%include "various.i"
%apply char **STRING_ARRAY { char **db }
%include "sab1.hpp"
Файл various.i
который вы связали, должен работать таким образом, просто поместите его где-нибудь, где SWIG сможет его найти, в вашем каталоге include или SWIG include path.
С помощью %include
вместо #include "sab1.hpp"
означает, что нам не нужно копировать определение классов, которые мы хотим обернуть. %apply
Директива применяет карту типов из various.i
на все аргументы char**
введите с именем db
, Если есть другие имена аргументов, которые вы хотите обернуть, добавьте их так:
%apply char **STRING_ARRAY { char **db, char **foo, char **bar }
Если вы просто хотите обернуть все аргумент типа char**
(небезопасно!), просто опустите имя:
%apply char **STRING_ARRAY { char ** }
Поскольку ваш код C ++ ожидает, что массив будет содержать 2 строки, тогда, пока вы передаете массив из 2 или более String
с Java, это должно быть хорошо. Карта типов добавит третий нулевой указатель в массив, но ваш код C ++ не заметит. Если вы передаете массив с менее чем 2 String
s, вы, вероятно, сломаете ваш код C ++.
Если какую-либо из функций C ++ вы также переносите возвращается массив строк, то у вас проблемы. SWIG попытается преобразовать их обратно в Java-массивы, но может потерпеть крах, когда будет искать третий элемент в массиве (он будет продолжать искать элементы, пока не найдет нулевой указатель). Если вы не возражаете отказаться от возвращаемого значения, вы можете сделать это:
%module Rec
%include "various.i"
%typemap(jni) char **db = char **STRING_ARRAY;
%typemap(jtype) char **db = char **STRING_ARRAY;
%typemap(jstype) char **db = char **STRING_ARRAY;
%typemap(in) char **db = char **STRING_ARRAY;
%typemap(freearg) char **db = char **STRING_ARRAY;
%typemap(javain) char **db = char **STRING_ARRAY;
%include "sab1.hpp"
Это будет применять только те части карты типов, которые имеют дело с входными аргументами.
Других решений пока нет …