BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #40088同步于 2015/4/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

关于JNA调用dll的问题

wbzj1110
2015/4/22镜像同步10 回复
c代码 _declspec(dllexport)struct coord_xy convert_bl_to_xy(struct coord_bl *coord_bl); struct coord_bl { int type; double lon, lat; }; struct coord_xy { int type; double x, y; }; 生成dll 然后java调用,下边java 代码 public interface TestDLL extends Library{ TestDLL INSTANCE = (TestDLL) Native .loadLibrary((Platform.isWindows() ? "XXXX" : "c"), TestDLL.class); public Coord_xy convert_bl_to_xy(Coord_bl.ByReference coord_bl); public static class Coord_bl extends Structure { public static class ByReference extends Coord_bl implements Structure.ByReference{} public static class ByValue extends Coord_bl implements Structure.ByValue{} public int type; public double lon, lat; } public static class Coord_xy extends Structure { public static class ByReference extends Coord_xy implements Structure.ByReference{} public static class ByValue extends Coord_xy implements Structure.ByValue{} int type; double x, y; } } public static void main(String[] args) { Coord_bl.ByReference bl = new Coord_bl.ByReference(); bl.type = Macro.COORD_BL; bl.lat = 39.26; bl.lon = 115.25; Coord_xy xy = TestDLL.INSTANCE.convert_bl_to_xy(bl); } 囧 每次都会报异常,跪求帮助。。。。 Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'convert_bl_to_xy': O?>>u 1/2 ?¨u at com.sun.jna.Function.<init>(Function.java:179) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:345) at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:325) at com.sun.jna.Library$Handler.invoke(Library.java:203) at $Proxy0.convert_bl_to_xy(Unknown Source) at etestJNA.JNAExtractorInterface.main(JNAExtractorInterface.java:42)
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
wbzj1110机器人#1 · 2015/4/22
额。。dll已经放到 当前工作目录。。。test的时候调用了一个简单的dll的show阔以调用到 应该不是找不到dll的原因哈,找不到dll会报load不进去 而不是UnsatisfiedLinkError
nuanyangyang机器人#2 · 2015/9/17
loadLibrary((Platform.isWindows() ? "XXXX" : "c") 这一行应该是JNA的例子上的代码吧。这段代码要把库名改成你的dll的路径。 是不是用C++编译器编译的呢?会进行name mangling的。如果是的话,要 extern "C"
wbzj1110机器人#3 · 2015/9/17
表示一开始想太多了。。没必要这么麻烦。。。其实本身是不想用c/c++的囧 被逼迫的 所以就换了一个思路 http://blog.csdn.net/wbzj1110/article/details/45557105 另:感谢暖羊羊大神回复。。。 【 在 nuanyangyang 的大作中提到: 】 : loadLibrary((Platform.isWindows() ? "XXXX" : "c") : 这一行应该是JNA的例子上的代码吧。这段代码要把库名改成你的dll的路径。 : 是不是用C++编译器编译的呢?会进行name mangling的。如果是的话,要 extern "C"
nuanyangyang机器人#4 · 2015/9/17
我这里有一个可以跑的版本。 我用的是JNA 4.2.0,不知你用的是哪个版本。 C代码 coord.c:我不会经纬度变换,就改成极坐标转直角坐标了。 #include <math.h> struct coord_polar { int type; double mag, ang; }; struct coord_xy { int type; double x, y; }; struct coord_xy convert_polar_to_xy(struct coord_polar *coord_polar) { struct coord_xy result; result.type = 42; result.x = coord_polar->mag * cos(coord_polar->ang); result.y = coord_polar->mag * sin(coord_polar->ang); return result; } 编译(linux):gcc -fPIC -shared -lm -o libcoord.so boord.c 生成的libcoord.so放在工作目录下的一个叫c的目录里。 Java代码: package cn.byr.nuanyangyang.coord; import java.util.Arrays; import java.util.List; import cn.byr.nuanyangyang.coord.CoordJNATest.TestDLL.Coord_polar; import cn.byr.nuanyangyang.coord.CoordJNATest.TestDLL.Coord_xy; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Structure; public class CoordJNATest { public interface TestDLL extends Library { TestDLL INSTANCE = (TestDLL) Native.loadLibrary("./c/libcoord.so", TestDLL.class); // 留意返回值的ByValue。如果不是ByValue,默认是认为返回struct指针的。 // // 官方文档如此叙述:https://github.com/java-native-access/jna/blob/master/www/StructuresAndUnions.md // When a function requires a pointer to a struct, a Java Structure // should be used. If the struct is passed or returned by value, you // need only make minor modifications to the parameter or return type // class declaration. // // 而Structure类的JavaDoc如是说: // Represents a native structure with a Java peer class. When used as a // function parameter or return value, this class corresponds to // struct*. When used as a field within another Structure, it // corresponds to struct. The tagging interfaces ByReference and ByValue // may be used to alter the default behavior. Structures may have // variable size, but only by providing an array field (e.g. byte[]). public Coord_xy.ByValue convert_polar_to_xy( Coord_polar.ByReference coord_polar); public static class Coord_polar extends Structure { public static class ByReference extends Coord_polar implements Structure.ByReference { } public static class ByValue extends Coord_polar implements Structure.ByValue { } public int type; public double mag, ang; // 这个方法要覆盖的。 @Override protected List<String> getFieldOrder() { return Arrays.asList("type", "mag", "ang"); } } public static class Coord_xy extends Structure { public static class ByReference extends Coord_xy implements Structure.ByReference { } public static class ByValue extends Coord_xy implements Structure.ByValue { } public int type; public double x, y; @Override protected List<String> getFieldOrder() { return Arrays.asList("type", "x", "y"); } } } public static void main(String[] args) { Coord_polar.ByReference bl = new Coord_polar.ByReference(); bl.type = 30; bl.mag = 2.0; bl.ang = Math.PI / 6.0; Coord_xy xy = TestDLL.INSTANCE.convert_polar_to_xy(bl); System.out.format("%d %f %f\n", xy.type, xy.x, xy.y); } } 输出: 42 1.732051 1.000000 看样子问题就是Structure作为参数和返回值的时候默认是ByReference而不是ByValue的。确实,把Struct当值传入和传出是很麻烦的,读ABI都能把人读得欲仙欲死,而且Windows和Linux不一样。
wbzj1110机器人#5 · 2015/9/18
是滴来 所以简单但是性能不知道是否有损失的方法,就是直接返回char* 也就是java的String就好啦。。——! 【 在 nuanyangyang 的大作中提到: 】 : 我这里有一个可以跑的版本。 : 我用的是JNA 4.2.0,不知你用的是哪个版本。 : C代码 coord.c:我不会经纬度变换,就改成极坐标转直角坐标了。 : ...................
wbzj1110机器人#6 · 2015/9/18
感谢~~暖羊羊大神~~[ema3] 【 在 nuanyangyang 的大作中提到: 】 : 我这里有一个可以跑的版本。 : 我用的是JNA 4.2.0,不知你用的是哪个版本。 : C代码 coord.c:我不会经纬度变换,就改成极坐标转直角坐标了。 : ...................
nuanyangyang机器人#7 · 2015/9/18
【 在 wbzj1110 的大作中提到: 】 : 是滴来 所以简单但是性能不知道是否有损失的方法,就是直接返回char* 也就是java的String就好啦。。——! 对了,今天中午开会,一个老师痛斥C语言的“允许按值返回struct”这个特性,他告诉我compcert C编译器(一个验证过的C编译器)对struct返回值的处理和别的C编译器(当然以及平台ABI)有所区别,总之比较麻烦。看来人们都不喜欢C语言这个特性。
wbzj1110机器人#8 · 2015/9/18
虽然明白细节。。但是大概意思就是不太推荐使用这个吧。。。[ema1]太高端了。。有点听不懂。。 【 在 nuanyangyang 的大作中提到: 】 : : 对了,今天中午开会,一个老师痛斥C语言的“允许按值返回struct”这个特性,他告诉我compcert C编译器(一个验证过的C编译器)对struct返回值的处理和别的C编译器(当然以及平台ABI)有所区别,总之比较麻烦。看来人们都不喜欢C语言这个特性。
nuanyangyang机器人#9 · 2015/9/18
嗯,是这个意思。最简单的方法就是再传一个指针,指向一个调用者分配好的struct空间。函数把返回值往里写就行了。 【 在 wbzj1110 的大作中提到: 】 : 虽然明白细节。。但是大概意思就是不太推荐使用这个吧。。。太高端了。。有点听不懂。。 来自「北邮人论坛手机版」