我有一些本机C ++代码,正在使用SWIG转换为Java,以便我的Java应用程序可以使用它。特别是有些函数返回std ::
vector。这是我的界面文件的一个片段:
%include "std_vector.i"
namespace std {
%template(Vector) vector<double>;
%template(Matrix) vector<vector<double> >;
}
%include "std_string.i"
std_string.i
并std_vector.i
包含在我正在使用的SWIG版本中。我的第一个惊喜是Java输出包含SWIG的Vector类的“自有”版本(与using相对java.util.Vector
)。我的真正问题是从这些函数返回的Vector似乎不起作用。例如,我无法使用get()
(有时会使程序崩溃)或size()
返回负值的函数来检索其内容。我知道Vector
s包含数据,因为我编码了相同功能的“字符串”版本,这些功能只是简单地遍历Vector
s(返回本机C
++代码)并以逗号分隔的String
值返回内容。尽管这是一个有效的解决方法,但最终我希望它能够与我一起使用并能够接收和操作Vectors
。任何帮助/提示将不胜感激。
std::vector
Java中自动换行的基本类型为java.util.AbstractList
。使用java.util.Vector
,因为你有两套存储,一个在最终的基地将是奇数std::vector
,还有一个在java.util.Vector
。
但是,SWIG不为您执行此操作的原因是因为您AbstractList<double>在Java中无法做到这一点,它必须是AbstractList<Double>
(Double
继承自Object
while
double
是原始类型)。
说了这么多我已经把一个小例子,它包装std::vector<double>
并`std::vector<std::vector
很好地在Java中。它还不完整,但是它支持Java和
set()/
get()`on元素中的“ for
each”迭代样式。足以说明如何/在需要时实施其他事情。
我将逐步介绍接口文件,但基本上,它们将是连续且完整的。
与开始num.i
定义我们的模块num
:
%module num
%{
#include <vector>
#include <stdexcept>
std::vector<double> testVec() {
return std::vector<double>(10,1.0);
}
std::vector<std::vector<double> > testMat() {
return std::vector<std::vector<double> >(10, testVec());
}
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("num");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}
我们有#include
用于生成的s
num_wrap.cxx
和两个用于测试的函数的实现(它们可能在单独的文件中,出于懒惰/方便的考虑,我将其放在此处)。
%pragma(java) jniclasscode=
我喜欢在Java SWIG接口中使用一个技巧,以使接口的用户透明地加载共享库/ DLL。
接口文件中的下一部分是std::vector
我们要包装的部分。我没有使用,std_vector.i
因为我们需要进行一些更改:
namespace std {
template<class T> class vector {
public:
typedef size_t size_type;
typedef T value_type;
typedef const value_type& const_reference;
%rename(size_impl) size;
vector();
vector(size_type n);
size_type size() const;
size_type capacity() const;
void reserve(size_type n);
%rename(isEmpty) empty;
bool empty() const;
void clear();
void push_back(const value_type& x);
%extend {
const_reference get_impl(int i) throw (std::out_of_range) {
// at will throw if needed, swig will handle
return self->at(i);
}
void set_impl(int i, const value_type& val) throw (std::out_of_range) {
// at can throw
self->at(i) = val;
}
}
};
}
这里是主要的变化%rename(size_impl) size;
,它告诉SWIG暴露size()
从std::vector
作为size_impl
代替。我们需要这样做,因为Java期望size
返回一个int
地方,因为std::vector
版本返回的地方size_type
很可能不会返回int
。
接下来在接口文件中,我们告诉我们要实现什么基类和接口,以及编写一些额外的Java代码以强制具有不兼容类型的函数之间的工作:
%typemap(javabase) std::vector<double> "java.util.AbstractList<Double>"
%typemap(javainterface) std::vector<double> "java.util.RandomAccess"
%typemap(javacode) std::vector<double> %{
public Double get(int idx) {
return get_impl(idx);
}
public int size() {
return (int)size_impl();
}
public Double set(int idx, Double d) {
Double old = get_impl(idx);
set_impl(idx, d.doubleValue());
return old;
}
%}
%typemap(javabase) std::vector<std::vector<double> > "java.util.AbstractList<Vector>"
%typemap(javainterface) std::vector<std::vector<double> > "java.util.RandomAccess"
%typemap(javacode) std::vector<std::vector<double> > %{
public Vector get(int idx) {
return get_impl(idx);
}
public int size() {
return (int)size_impl();
}
public Vector set(int idx, Vector v) {
Vector old = get_impl(idx);
set_impl(idx, v);
return old;
}
%}
这设置了java.util.AbstractList<Double>
for
std::vector<double>
和java.util.AbstractList<Vector>
for
的基类`std::vector<std::vector
(这
Vector是我们将
std::vector`在接口的Java端调用的基类)。
我们还在Java方面提供get
和的实现set
,可以处理double
到Double
转换并再次返回。
最后,在界面中添加:
namespace std {
%template(Vector) std::vector<double>;
%template(Matrix) std::vector<vector<double> >;
}
std::vector<double> testVec();
std::vector<std::vector<double> > testMat();
这告诉SWIG指std::vector<double>
(与特定类型),其Vector
同样地,对于`std::vector<vector
如
Matrix`。我们还告诉SWIG公开我们的两个测试功能。
接下来test.java
,,这main
是Java中的一个简单示例,它可以稍微练习一下我们的代码:
import java.util.AbstractList;
public class test {
public static void main(String[] argv) {
Vector v = num.testVec();
AbstractList<Double> l = v;
for (Double d: l) {
System.out.println(d);
}
Matrix m = num.testMat();
m.get(5).set(5, new Double(5.0));
for (Vector col: m) {
for (Double d: col) {
System.out.print(d + " ");
}
System.out.println();
}
}
}
要构建并运行它,我们要做:
swig -java -c++ num.i
g++ -Wall -Wextra num_wrap.cxx -shared -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux/ -o libnum.so
javac test.java && LD_LIBRARY_PATH=. java test
我在Linux / x86上使用g ++版本4.4和SWIG 1.3.40对此进行了测试。
的完整版本num.i
可以在此处找到,但始终可以通过将每个部分粘贴到一个文件中来从此答案中重建。
我尚未实现的事情AbstractList
:
add()
-可以通过push_back()
,std_vector.i来实现,默认情况下甚至尝试实现兼容的东西,但是它不适用于Double
vs double
问题或与AbstractList
(不要忘记增加modCount
)中指定的返回类型匹配remove()
- std::vector
就时间复杂度而言不是很好,但也不是不可能实现(同样使用modCount
)Collection
建议使用另一个构造函数,但此处未实现。可以在同一个地方执行set()
和get()
是的,但需要$javaclassname
正确地命名生成的构造函数。size_type
-> int
转换size()
是否正确。我使用ApacheStorm与Apache Kafka。使用的喷口是Kafka喷口,但它没有阅读Kafka主题的任何内容。我不知道这是否与我在暴风的工人中面临的问题有关。如果您知道任何相关解决方案,请告知我。 Storm拓扑已成功上载到Storm。我获取了日志,下面是工作人员在其文件:
我正在使用SWIG生成一个围绕freetype的C包装。我的目标是为WinRT生成一个带有C接口的freetype DLL,该接口将在Windows Phone 8上运行,然而,生成的C包装似乎依赖于Tcl。由于我不需要Tcl绑定,而且WinRT默认情况下不提供Tcl,我想知道是否可以以某种方式关闭Tcl依赖项。我正在使用Visual Studio 2012编译生成的代码。 我查阅了文档,只找到了
我目前在编译protobuf生成的C代码时遇到了一些问题<代码>协议(code>protoc)运行正常,不会显示任何警告,但是,当我尝试编译生成的C代码以便构建静态库时,g向我显示以下消息: CanInfo。pb。抄送:107:5:错误:“::protobuf\u BusType\u 2eproto”尚未声明107;::protobuf\u BusType\u 2eproto::AddDescri
问题内容: 以下子组件从其父组件接收道具。然后,使用将道具设置为自己的状态,并使用将值渲染到相应的输入字段。 我用来在子组件收到新道具时更新其状态。 最初,调用该组件时,它可以正常工作。问题是第二次通过道具时发生的,触发道具通过的相应按钮需要两次单击才能设置孩子的状态。 我可能使用不正确? 完整代码: 问题答案: 我可能会错误地使用componentWillRecieveProps? 是的,因为您
Gradle版本:5.1 Java版本:11 我在gradle文件中定义了以下任务来生成QueryDSL类: 下面是我的依赖项块: 如果我执行'gradlew generateQClasses,我会在日志中看到以下内容: 它失败,错误是文件已经存在。如何配置此任务以覆盖文件(如果存在)? 此外,上面的配置是根项目的配置,它有5个子项目。能够覆盖其中一个子项目中的文件,但不能覆盖其他子项目中的文件(
问题内容: public class MyThread { volatile static int i; 由于易失性构建发生在关系之前,因此i的最终值应严格为2000000。但是,实际结果与变量i不具有易失性没有什么不同。谁能解释为什么它在这里不起作用?由于我被声明为volatile,因此应该保护它免受内存不一致的影响。 问题答案: 谁能解释为什么它在这里不起作用?由于我被声明为volatile,