我有一个带有虚方法的C ++类。我使用的是导演,我在Java中对C ++类进行了细分。此类用于接收来自C ++代码的回调。然后将Java类传递给C ++和C ++调用其上的方法(upcalls to Java)。有数组参数(或指针数组,我已尝试过两者)并将它们转换为SWIGTYPE_p_double。
我想有一个双面[]的Java边类型签名,当然还有double []参数中的数组内容(复制内容很好)。
我该怎么做?
我已经尝试过以下代码,我从一些电子邮件列表中提取了这些代码:
c_backend.i:
%module(directors="1") c_backend
%{
#include "c_backend.h"
%}
%typemap(directorin, descriptor="[D") (double *DOUBLE, size_t LENGTH) {
jdoubleArray jd = (jenv)->NewDoubleArray($2);
(jenv)->SetDoubleArrayRegion(jd, 0, $2, (jdouble *)$1);
$input = jd;
}
%typemap(directorargout) (double *DOUBLE, size_t LENGTH)
%{(jenv)->GetDoubleArrayRegion($input, 0, $2, (jdouble *)$1); %}
%feature("director") CallbackHandler;
%include "c_backend.h"
c_backend.h:
#ifndef CALLBACK_HANDLER_H
#define CALLBACK_HANDLER_H
#include <stdio.h>
class CallbackHandler {
public:
virtual ~CallbackHandler() {}
virtual void statusUpdate( double *params, size_t size ) {
printf("in C++ statusUpdate\n");
}
};
class Server {
public:
void doSomething( CallbackHandler * );
};
#endif
c_backend.cpp:
#include "c_backend.h"
#include <stdio.h>
#include <stdlib.h>
void Server::doSomething( CallbackHandler *ch ) {
double *params = (double *)malloc(3*sizeof(double));
params[0] = 1.1;
params[1] = 2.2;
params[2] = 3.3;
printf("In doSomthing\n");
ch->statusUpdate(params,3);
printf("exiting doSomthing\n");
}
JavaFrontend.java:
public class JavaFrontend {
static {
System.loadLibrary("CBackend");
}
public static void main( String[] args ) {
JFCallbackHandler jf = new JFCallbackHandler();
new Server().doSomething(jf);
}
public static class JFCallbackHandler extends CallbackHandler {
public void statusUpdate( double params[], long size ) {
System.out.println("Java got params: "+params);
}
}
}
要编译的Makefile:
JAVA_INCLUDE=-I/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/include/darwin
all:
c++ -c c_backend.cpp
swig -java -c++ $(JAVA_INCLUDE) c_backend.i
c++ $(JAVA_INCLUDE) -c c_backend_wrap.cxx
c++ -dynamiclib -o libCBackend.jnilib *.o -framework JavaVM
javac *.java
clean:
rm -rf *.class *.o *_wrap.cxx *_wrap.h Server.java SWIGTYPE*.java c_backend*.java CallbackHandler.java
Swig -version:
SWIG版本3.0.8
使用clang ++编译[x86_64-apple-darwin15.2.0]
配置选项:+ pcre
有关报告错误的信息,请参阅http://www.swig.org 信息
答案 0 :(得分:1)
我付出了一些努力。您找到的作为起点的类型图是合理的,但我认为不完整。我不认为你可以在没有匹配in / jtype / jstype / jni / javadirectorin / javain的情况下逼真地编写directorin / directorargout类型图,因为你很快就会在生成的代码的各个片段之间产生不匹配的期望。 (导演代码也可以调用常规Java类,也可以调用它)。
此外,我认为使用多参数类型映射将指针和大小参数压缩到Java中的单个参数会更好,因为长度隐式是Java中数组的属性。
所以这里有一个简要的总结,说明我必须做些什么才能让它发挥作用:
%apply
是做到这一点的巧妙方法,特别是对于像这样的多参数类型图。double[]
从C ++传递到Java的类型映射。double[]
并且是隐式大小,测试用例需要更新以确保它仍然是覆盖而不是重载。为了更好的衡量,我添加了@Override
。我做了一些风格上的改变,因为他们的代码更好:
double*
- > jdouble*
),但最糟糕的是它们会隐藏一些不合适的东西。所以最后您的SWIG界面如下所示:
%module(directors="1") c_backend
%{
#include "c_backend.h"
%}
%typemap(jstype) (double *DOUBLE, size_t LENGTH) "double[]"
%typemap(jtype) (double *DOUBLE, size_t LENGTH) "double[]"
%typemap(jni) (double *DOUBLE, size_t LENGTH) "jdoubleArray"
%typemap(javadirectorin) (double *DOUBLE, size_t LENGTH) "$jniinput"
%typemap(javain) (double *DOUBLE, size_t LENGTH) "$javainput"
%typemap(in,numinputs=1) (double *DOUBLE, size_t LENGTH) {
// Note the NULL here if you don't want to be making changes visible
$1 = JCALL2(GetDoubleArrayElements, jenv, $input, NULL);
$2 = JCALL1(GetArrayLength, jenv, $input);
}
%typemap(freearg) (double *DOUBLE, size_t LENGTH) {
// Swap 0 for JNI_ABORT if you don't want to make changes visible
JCALL3(ReleaseDoubleArrayElements, jenv, $input, $1, 0);
}
%typemap(directorin,descriptor="[D") (double *DOUBLE, size_t LENGTH) {
$input = JCALL1(NewDoubleArray, jenv, $2);
JCALL4(SetDoubleArrayRegion, jenv, $input, 0, $2, $1);
}
%typemap(directorargout) (double *DOUBLE, size_t LENGTH) {
(jenv)->GetDoubleArrayRegion($input, 0, $2, $1);
}
%feature("director") CallbackHandler;
%apply (double *DOUBLE, size_t LENGTH) { (double *params, size_t size) };
%include "c_backend.h"
这足以使您的测试用例正确地使用上述更改来使其覆盖而不是现在过载。