我在C方面
typedef struct {} C_String;
C_String* StringNew();
void StringFree(C_String* string);
在Java上我得到了这样的包装类
public class String {
private long swigCPtr;
protected boolean swigCMemOwn;
protected String(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr(String obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
protected void finalize() {
delete();
}
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
JNI.delete_C_String(swigCPtr);
}
swigCPtr = 0;
}
}
public String() {
this(JNI.new_C_String(), true);
}
}
JNI.new_С_String和JNI.delete_С_String是SWIG生成的本机方法,它们执行简单的工作 - 按C_String
分配malloc
并分别按free
删除它。在我的情况下,情况应该是不同的,因为C_String
是空结构并且行为类似于快捷方式,应该由StringNew
分配,malloc
由StringFree
引导并由JNI.new_String
释放。
我想使用正确的方法代替JNI.delete_String
,"SELECT "
+ "CASE WHEN smth.status != 'BATMAN' THEN ... "
+ "ELSE (SELECT ... FROM ... WHERE ... ORDER BY ... DESC limit 1) "
+ "END, "
+ "next_field, "
+ "CASE WHEN smth.status == 'BATMAN' THEN ... "
+ "ELSE ... "
+ "END, "
+ "final_field_which_doesent_have_a_case_logic"
+ "FROM ... the_rest_of_the_normal_query";
最简单的方法是什么?
答案 0 :(得分:2)
假设您显示的C位于名为test.h的文件中,以下SWIG界面将执行您想要的操作:
%module test
%{
#include "test.h"
%}
%extend C_String {
C_String() {
return StringNew();
}
~C_String() {
StringFree($self);
}
}
%ignore StringNew;
%ignore StringFree;
%include "test.h"
这使用%extend
为C_String
类型提供自定义构造函数和析构函数。此构造函数/析构函数对分别只调用C函数StringNew
和StringFree
。
在您的问题中,您要求在生成的Java代码中进行这些调用。我上面写的方式使这些调用发生在C语言中。这有两个主要好处:
这个答案的其余部分主要是作为一个学习点,而不是推荐的解决方案。
如果你真的想要,你可以把它写成Java,然后进行你要求的JNI电话。要做到这一点,你需要写一些typemaps,你至少需要两个(未经测试的)看起来像这样的东西:
javabody:
%typemap(javabody) C_String %{
private long swigCPtr;
protected boolean swigCMemOwn;
protected $javaclassname(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
public $javaclassname() {
$javaclassname tmp = $imclassname.StringNew();
swigCMemOwn = tmp.swigCMemoryOwn;
swigCPtr = tmp.swigCPtr;
tmp.swigCMemoryOwn = false;
}
protected static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
javadestruct:
%typemap(javabody) C_String %{
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
$imclassname.StringFree(swigCPtr);
}
swigCPtr = 0;
}
}
%}
但如前所述,这确实不是解决问题的最佳方法。 (如果您希望在继承的情况下仍然如此,那么您还需要' javadestruct_derived' typemap)