使用SWIG Directors将数组从C 传递到Java
Passing arrays from C++ to Java using Swig directors, the up call
我有一个带有虚拟方法的C 类。我正在使用董事,并在Java中属于C 类。此类用于从C 代码接收回调。因此,Java类然后将其传递到其上的C 和C 调用方法(呼叫到Java)。有数组参数(或指针数组,我两者都尝试过),然后将它们转换为swigtype_p_double。
我想拥有一个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++ statusUpdaten");
}
};
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 doSomthingn");
ch->statusUpdate(params,3);
printf("exiting doSomthingn");
}
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);
}
}
}
和一个编译的制作费:
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进行报告,并进一步报告 信息
我付出了一些努力。您发现作为起点的打字是合理的,但我认为不是完整的。我认为您无法实际编写Directorin/Directorargout Typemaps,而无需在/JTYPE/JSTYPE/JNI/JNI/JAVADIRECTORIN/JAVAIN ONE中进行匹配,因为您很快就会迅速在生成代码的各个片段之间遇到不匹配的期望。(主管代码也可以调用常规Java类,也可以通过它来调用)。
另外,我认为最好使用多距离Typemap将指针和大小的尺寸凝结到Java内部的单个参数,因为长度隐含地是Java中一个数组的属性。
。因此,这是我必须做的使它起作用的快速摘要:
- 首先,您现有的打字不会应用于代码,因为它们在参数类型和参数名称上都匹配。
%apply
是这样做的整洁方法,尤其是对于这样的多重题词打字。 - 其次,添加了相应的打字件,而不仅仅是导演。
- 第三,添加了通过代理从C 到Java的
double[]
的添加类型。 - 最后,由于类型现在仅仅是
double[]
,并且隐含的大小需要更新测试用例,以确保其替代而不是超载。为了好的措施,我添加了@Override
。
和我进行的一些风格上的更改,因为它们是更好的代码:
- 将铸件从键入输入输入到jdouble。充其量它们应该是no -op(
double*
->jdouble*
),但最糟糕的是,他们会隐藏一些东西。 - 将Typemaps设置为自己的街区。这意味着您可以在同一函数上两次使用相同的Typemap,而不会冲突本地变量名称。(尽管我最终都删除了本地变量)
- 使用Swig的Jcallx Macros-这显然是C 代码,但这是我在编写Swig代码时尝试保留的习惯。
最终您的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"
足以使您的测试案例在上述更改中正确工作以使其覆盖而不是现在超负荷。
- SWIG Java 在使用 -DSWIGWORDSIZE64 时将int64_t转换为 jlong
- Java SWIG wrapper vs direct function calling
- 在 Java 中使用 std::vector和 SWIG
- SWIG:如何处理生成的 Java 代码中的指针
- 如何<UserDefinedClass>通过 Swig 将带有数据的 std::vector 传递给 Java?
- Swig:如何将"FILE"类型从 C++ 传递给 Java
- 使用SWIG Directors将数组从C 传递到Java
- 在SWIG和Visual Studio 2015中使用Java中编译的DLL
- SWIG - Java 代理类数组参数
- 使用 SWIG 将 c++ 包装到 java 不满意的链接错误: HeaderJNI.new_Test()J.
- 通过Swig在Java中处理C 例外
- 将简单的 Java 数组传递给原始的 C 数组 SWIG
- Java和SWIG:类集成到一个包中
- 让SWIG理解在Java中使用char**
- 您将如何为 std::list<std::string> 创建一个类型映射,以在<String> List in C++ 中为 Java 在 SWIG 中创建?
- SWIG/Java:对象过早地获得GCed
- 在Windows中使用swig从Java调用c ++函数,得到java.lang.UnsatisfiedLinkErro
- 如何使用Swig将数组(java中的长数组)从Java传递到C++
- 使用 SWIG 将 Java Map<String、String> 传递给C++方法
- Java 不会从使用 swig 创建的.dll调用函数