使用JavaCPP调用带CTB_DLL导出宏的C++类出现ClassNotFoundException如何解决
JavaCPP调用ctb::Terrain抛出ClassNotFoundException解决方案
问题根因
出现该异常是由代码结构错误、映射规则不符合JavaCPP要求、执行命令逻辑错误三类问题共同导致的:
- 注解配置位置错误:
@Platform、@Namespace注解应该放在对应C++类的映射Java类上,你错误放在了外层无关的TerrainTile类上 - 构造函数映射错误:JavaCPP中使用
allocate()方法对应C++构造函数,多余的native void Terrain()方法会导致编译失败,无法生成有效class文件 - 命令逻辑错误:JavaCPP的Builder工具处理的是编译后的class文件,直接传入java源文件会找不到对应类
- 参数类型映射错误:C++的
const char*对应Java的String加@Cast注解,你错误使用了Pointer类型,会导致类生成异常
解决步骤
1. 修正Java映射代码
import org.bytedeco.javacpp.*; import org.bytedeco.javacpp.annotation.*; // 注解放在映射类上,link参数填你C++代码编译生成的动态库名称 @Platform(include = "TerrainTile.hpp", link = "ctb") @Namespace("ctb") public class Terrain extends Pointer { static { Loader.load(); } // 映射空构造函数 public Terrain() { allocate(); } private native void allocate(); // 映射const char*参数的构造函数 public Terrain(@Cast("const char*") String fileName) { allocate(fileName); } private native void allocate(@Cast("const char*") String fileName); // 映射readFile方法 public native void readFile(@Cast("const char*") String fileName); // 映射writeFile方法,FILE*直接映射为Pointer即可 public native void writeFile(Pointer fp); public static void main(String[] args) { Terrain terrain = new Terrain(); // 测试功能 terrain.readFile("你的地形数据文件路径"); } }
2. 编译Java源文件
执行javac命令,将javacpp包加入类路径:
javac -cp javacpp-1.5.5.jar Terrain.java
3. 调用JavaCPP生成JNI代码和动态库
Linux/macOS执行:
java -cp .:javacpp-1.5.5.jar org.bytedeco.javacpp.tools.Builder TerrainWindows执行:
java -cp .;javacpp-1.5.5.jar org.bytedeco.javacpp.tools.Builder Terrain
4. 运行测试
Linux/macOS执行:
java -cp .:javacpp-1.5.5.jar TerrainWindows执行:
java -cp .;javacpp-1.5.5.jar Terrain
注意事项
- C++头文件
TerrainTile.hpp需要放在当前执行目录,或在@Platform的include参数中添加头文件搜索路径 - C++编译生成的ctb动态库(libctb.so/ctb.dll/libctb.dylib)需要放在系统库搜索路径,或在
@Platform的linkpath参数中添加库搜索路径 - 所有命令执行的工作目录需要和class文件所在目录保持一致
内容的提问来源于stack exchange,提问作者KuCao
相关产品推荐
相关产品推荐

