Java 如何使用SWIG包装std::function对象?
我见过不少类似的问题,但还没有找到解决我这个问题的办法。我正在尝试编写一些使用std::function的C++11代码,以便在Java应用程序中使用它 我遇到过这样的共享指针:Java 如何使用SWIG包装std::function对象?,java,c++,c++11,swig,std-function,Java,C++,C++11,Swig,Std Function,我见过不少类似的问题,但还没有找到解决我这个问题的办法。我正在尝试编写一些使用std::function的C++11代码,以便在Java应用程序中使用它 我遇到过这样的共享指针: virtual std::shared_ptr<some::ns::TheThing> getTheThing(unsigned short thingID); virtual std::vector<std::shared_ptr<some::ns::TheThing>> get
virtual std::shared_ptr<some::ns::TheThing> getTheThing(unsigned short thingID);
virtual std::vector<std::shared_ptr<some::ns::TheThing>> getAllTheThings() const = 0;
void registerThingCallback(std::function<void(std::shared_ptr<some::ns::TheThing>) > func);
我遇到过这样的共享指针向量:
virtual std::shared_ptr<some::ns::TheThing> getTheThing(unsigned short thingID);
virtual std::vector<std::shared_ptr<some::ns::TheThing>> getAllTheThings() const = 0;
void registerThingCallback(std::function<void(std::shared_ptr<some::ns::TheThing>) > func);
不幸的是,来自简单Java主代码的大多数方法现在都获取或返回这些对象,这使得它们相当不可用。你知道怎么解决这个问题吗?谢谢大家!
更详细一点的完整性:我使用以下三个脚本来编译和运行代码。参数略有不同,但我认为这无关紧要。在我这方面,它被设置为一个EclipseMaven项目。这些脚本位于我的项目的根目录中,头文件和swig文件位于src/main/resources中,java源文件位于src/main/java中,java编译类位于target/classes中。Eclipse执行java编译
swigthing.sh
compileThingSwigTest.sh
runThingTest.sh
最后更新
修复了上面的代码,将正确的参数传递给std_函数。现在,在问题和答案之间有一个完整的工作示例,说明了我所追求的。尽管SWIG不提供std_功能。我认为我们可以自己构建一个,这需要一些工作。这里我的答案是我的a的一个更一般化的版本,针对一个特定的实例研究这个问题,并以Python为目标。我将对它进行多次迭代,为泛型
std::function
包装定义一个%std\u函数
宏
我假设您希望通过包装std::function
实现四件事,这成为我们的主要需求:
std::function
对象std::function
对象需要像任何其他对象一样传递,包括在任意方向跨越语言边界shared\u ptr
部分进行了润色,它实际上并没有改变任何事情,因为当你在shared\u ptr
工作时,它实际上也足以在这个场景中使用,这只会让我的示例变得更加冗长,不必要
我正在研究的解决方案实际上是根据SWIG中现有的shared_ptr
支持建模的。我准备了一个测试界面来说明如何使用它:
%模块测试
%包括“std_function.i”
%std_函数(函子,void,int,double);
%{
#包括
%}
%内联%{
std::函数make_函子(){
返回[](整数x,双y){
std::cout call(对于每个(转发,虚拟参数));
});
}
}
};
}
%enddef
和Test.I略微扩展,以验证java > C++传递的<>代码>:函数:< /Cord>对象,使能执行器:
%模块(directors=“1”)测试
%包括“std_function.i”
%std_函数(函子,void,int,double);
%{
#包括
无效添加和打印(整数a,双b){
std::cout你的目标语言是什么?这是一个起点,但也有其他选择。D'oh刚刚看到Java标签。我会在周末尝试找到答案。如果不清楚的话,很抱歉,是的,是Java。提前谢谢你,同时我会看你发布的链接。哇,这是一个(典型的,让你看看你的历史)回答得很好。我仍在完成你今天早些时候发布的前半部分,我需要一点时间来完成和消化所有这些。我要么跟进问题,要么在感觉良好时接受。谢谢!我马上就有一个问题是,这是否适用于swig 3.0?@据我所知的可变模板否认SWIG 3.0中的ate支持仍然不足以正确处理std::function
,但我所写的应该在可预见的将来仍然有效。@否认我刚才所做的两次编辑中的第一次修复了一系列错误,一次是我昨天在回答中提到的垃圾收集问题,另一次是停止了完整的sol如果你调用这个类而不是Functor
,那么它就正常工作了。好的,我已经有机会解决了这个问题,并且在问题中发布了一个新的细节更新。
#ifndef THE_THING_H
#define THE_THING_H
#include <string>
namespace some {
namespace ns {
class TheThing {
public:
virtual ~TheThing() {};
virtual unsigned long longThing() const = 0;
virtual std::string stringThing() const = 0;
};
}
}
#endif /* THE_THING_H */
%module(directors="1") Thing
%include "stl.i"
%include "std_function.i"
%include "std_shared_ptr.i"
%shared_ptr(some::ns::TheThing);
%typemap(javadirectorin) std::shared_ptr<some::ns::TheThing> "new $typemap(jstype, some::ns::TheThing)($1,false)";
%typemap(directorin,descriptor="Lsome.ns.typemap(jstype, some::ns::TheThing);") std::shared_ptr<some::ns::TheThing> %{
*($&1_type*)&j$1 = &$1;
%}
%include "test_thing.h"
%include "thing_callback.h"
%{
#include <memory>
#include "test_thing.h"
#include "thing_callback.h"
%}
%std_function(Functor, void, std::shared_ptr<some::ns::TheThing>);
%{
#include <iostream>
void add_and_print(std::shared_ptr<some::ns::TheThing> thing) {
std::cout << "here\n";
}
%}
%callback("%s_cb");
void add_and_print(std::shared_ptr<some::ns::TheThing>);
%nocallback;
%inline %{
std::function<void(std::shared_ptr<some::ns::TheThing>)> make_functor() {
return [](std::shared_ptr<some::ns::TheThing>){
std::cout << "make functor\n";
};
}
void do_things(std::function<void(std::shared_ptr<some::ns::TheThing>)> in) {
std::cout << "inside do things\n";
}
%}
SWIGTYPE_p_f_std__function__f_std__shared_ptr__some__ns__TheThing____void____void
SWIGTYPE_p_f_std__shared_ptr__some__ns__TheThing____void
SWIGTYPE_p_std__functionT_void_fstd__shared_ptrT_some__ns__TheThing_tF_t
MODULE_NAME=Thing
PACKAGE=some.ns
OUTDIR=./src/main/java/some/ns
I_FILE=./src/main/resources/func_thing_test.i
mvn clean
rm $OUTDIR/*.*
mkdir -p $OUTDIR
swig -java -c++ -module $MODULE_NAME -package $PACKAGE -outdir $OUTDIR $I_FILE
./compileThingSwigTest.sh
#!/bin/bash
pushd src/main/resources
g++ -c -std=gnu++11 -fpic \
func_thing_test_wrap.cxx \
-I/usr/lib/jvm/java/include \
-I/usr/lib/jvm/java/include/linux
g++ -shared func_thing_test_wrap.o -o libFunc.so
popd
pushd target/classes
java -Xmx512M -Xms512M -Djava.library.path=. some.ns.test.RunThingTest
popd
%std_function(Name, Ret, ...)
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
test.make_functor().call(1,2.5);
}
}
// Conversion constructor from function pointer
function<Ret(__VA_ARGS__)>(Ret(*const)(__VA_ARGS__));
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
test.make_functor().call(1,2.5);
new Functor(test.add_and_print_cb).call(3,4.5);
}
}
public class run extends Functor {
public static void main(String[] argv) {
System.loadLibrary("test");
test.make_functor().call(1,2.5);
new Functor(test.add_and_print_cb).call(3,4.5);
Functor f = new run();
test.do_things(f);
}
@Override
public void call(int a, double b) {
System.out.println("Java: " + a + ", " + b);
}
}
%extend {
function<Ret(__VA_ARGS__)>(Name##Impl *in) {
return new std::function<Ret(__VA_ARGS__)>([=](auto&& ...param){
return in->call(std::forward<decltype(param)>(param)...);
});
}
}
%shared_ptr(some::ns::TheThing);
%typemap(javadirectorin) std::shared_ptr<some::ns::TheThing> "new $typemap(jstype, some::ns::TheThing)($1,false)";
%typemap(directorin,descriptor="L$typemap(jstype, some::ns::TheThing);") std::shared_ptr<some::ns::TheThing> %{
*($&1_type*)&j$1 = &$1;
%}