TL; DR :查看this repo并阅读自述文件中的说明。
我想使用SWIG生成JNI代码,以与具有结构体(函数指针)的C库进行接口连接。函数指针指向的函数是在C库中定义的,因此我只希望能够从Java代码中调用它。下面是更多详细信息。
假设我在文件database.c
中定义了一个C结构和相关代码:
#include <string.h>
#include <stdlib.h>
struct MyDatabase;
typedef struct MyDatabase MyDatabase;
typedef int (*SomeFuncPtr)(const char *name);
struct MyDatabase {
char *name;
SomeFuncPtr fPtr;
};
int myFunc(const char *name) {
return strlen(name);
};
struct MyDatabase *new_database(char *name) {
MyDatabase *myDB = malloc(sizeof(struct MyDatabase));
myDB->name = strdup(name);
myDB->fPtr = &myFunc;
return myDB;
};
附带的标题database.h
如下所示:
struct MyDatabase;
typedef struct MyDatabase MyDatabase;
typedef int (*SomeFuncPtr)(const char *name);
struct MyDatabase {
char *name;
SomeFuncPtr fPtr;
};
struct MyDatabase *new_database(char *name);
我有一个SWIG接口文件database_swig.i
,看起来像这样:
%module database
%{
#include "database.h"
%}
%nodefaultctor MyDatabase;
%nodefaultdtor MyDatabase;
%include "database.h"
%include "cpointer.i"
%pointer_functions(MyDatabase, MyDatabaseHandle)
生成的代码面临两个问题:
SomeFuncPtr fPtr;
一部分的函数指针struct MyDatabase
。SWIG生成的JNI代码允许我执行以下操作:
SWIGTYPE_p_MyDatabase myDBPtr = database.new_database("testing");
MyDatabase myDB = database.MyDatabaseHandle_value(myDBPtr);
myDB.getFPtr("hello"); // doesn't work - says that no arguments are expected
SWIGTYPE_p_f_p_q_const__char__int myFunc = myDB.getFPtr();
myFunc("hello"); // error about "Method call expected"
但是涉及到getFPtr
的两个调用都导致错误,如上面代码中的注释中所述。
%pointer_functions(MyDatabase, MyDatabaseHandle)
生成的SWIG生成的JNI粘合代码导致:public static SWIGTYPE_p_MyDatabase MyDatabaseHandle_value(SWIGTYPE_p_MyDatabase obj) {
return new SWIGTYPE_p_MyDatabase(databaseJNI.MyDatabaseHandle_value(SWIGTYPE_p_MyDatabase.getCPtr(obj)), true);
}
当我真的想要类似的东西时:
public static MyDatabase MyDatabaseHandle_value(SWIGTYPE_p_MyDatabase obj) {
return new MyDatabase(databaseJNI.MyDatabaseHandle_value(SWIGTYPE_p_MyDatabase.getCPtr(obj)), true);
}
这是我在提交给仓库linked to above的代码中手动对其进行编辑的内容。
this question中描述了与上述第二个问题非常相似的事物。
更新:
我发现this answer使用database.h
中的以下内容帮助我完成了工作:
#ifdef SWIG
#define MEMBER(name, args) name args
#else
#define MEMBER(name, args) (*name) args
#endif
struct MyDatabase {
char *name;
int MEMBER(fPtr,(const char *));
};
这有效,但理想情况下,我希望能够将typedef用作函数指针typedef int (*SomeFuncPtr)(const char *name);
。
关于如何使它起作用的任何想法?