从本机代码返回`const char *`并在java中获取`String`
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了从本机代码返回`const char *`并在java中获取`String`,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4302字,纯文字阅读大概需要7分钟。
内容图文
我正在使用JNA将我的C代码与java连接.我有一个本机函数,它接受一个字符串作为输入并返回一个字符串作为输出.
以下是该函数的C实现.
const char* decrypt(char* value){
std::string res = TripleDes::getInstance().decrypt(value);
std::cout<<res.c_str()<<"\n";
return res.c_str();
}
我正在使用JNA在一个简单的java程序中加载此函数,并尝试从java获取一个字符串.问题是,我从java得到一个空字符串.以下是java代码:
interface NativeExample extends Library {
NativeExample ne = (NativeExample) Native.loadLibrary("foo", NativeExample.class);
String decrypt(String value);
}
public class Main{
public static void main(String[] args){
String decrypted = NativeExample.ne.decrypt("foo");
System.out.println(decrypted);
}
}
来自C代码的打印值是完美的,但是从Java开始,会打印一个空字符串.我见过这个question,但它为JNI提供了解决方案.我想使用JNA并返回一个字符串.我该怎么办呢?
我还尝试返回JNA Pointer类型并在其上调用getString()方法.但打印乱码,这在所有调用中都不相同.
我知道我在函数范围内返回一个悬空指针,它会在到达java调用时被破坏.我想要一个简单的解决方案,我可以使用JNA将C代码中的String返回给Java.
在JNA文档here中提到,您应该在java中使用String作为C/C++中相应的const char *.
解决方法:
Caninonos的回答充分解释了这个问题.这是两种不同的解决方案.
A)动态分配字符串并提供释放它的功能
你将不得不以某种方式释放字符串,所以要正确地做.提供一个函数,它接收返回的指针并释放它.考虑将AutoCloseable与try-with-resources语句一起使用.
C
char* decrypt(char* value) {
std::string res = TripleDes::getInstance().decrypt(value);
std::cout << res.c_str() << "\n";
return strndup(res.c_str(), res.size());
}
void free_decrypted_string(char* str) {
free(str);
}
Java的
interface NativeExample extends Library {
NativeExample ne = (NativeExample) Native.loadLibrary("foo", NativeExample.class);
Pointer decrypt(String value);
void free_decrypted_string(Pointer str);
}
public class Main {
public static void main(String[] args) {
Pointer decrypted = NativeExample.ne.decrypt("foo");
System.out.println(decrypted.getString(0));
NativeExample.ne.free_decrypted_string(decrypted);
}
}
如果您选择使用AutoClosable,您可以从自定义PointerType中受益,JNA允许您将其用作指针的几乎可直接替代品.但是,由于您只是刚刚获得结果,因此最好将JNA接口封装在处理释放的Java“decryptor”类中. AutoClosable更适合文件或进程句柄之类的东西.
interface NativeExample extends Library {
NativeExample ne = (NativeExample) Native.loadLibrary("foo", NativeExample.class);
FreeableString decrypt(String value);
void free_decrypted_string(FreeableString str);
class FreeableString extends PointerType implements AutoCloseable {
@Override
public void close() {
ne.free_decrypted_string(this);
}
public String getString() {
return this.getPointer().getString(0);
}
}
}
public class Main {
public static void main(String[] args) {
try (NativeExample.FreeableString decrypted = NativeExample.ne.decrypt("foo")) {
System.out.println(decrypted.getString());
}
}
}
B)更改decrypt函数以接受输出缓冲区
您可以使用输出参数,而不必记住释放动态分配的字符串.理想情况下,您希望使用size_t而不是int,但使用它从JNA有点尴尬.如果需要使用长于int max的字符串,请计算出size_t.
由于您使用的是Triple DES,因此它可能会应用填充,因此输出的大小可能与输入的长度不同.为了解决这个问题,如果缓冲区太小,函数会输出所需的大小.
请注意,该函数不写空终止符,因此请确保使用返回的值.
C
int decrypt(const char *value, char *output, int *output_size) {
std::string res = TripleDes::getInstance().decrypt(value);
std::cout << res.c_str() << "\n";
if (*output_size < res.size()) {
*output_size = res.size();
return 0;
}
size_t bytes_written = res.copy(output, *output_size);
return (int)bytes_written;
}
Java的
interface NativeExample extends Library {
NativeExample ne = (NativeExample) Native.loadLibrary("foo", NativeExample.class);
int decrypt(String value, byte[] output, IntByReference outputBufferSize);
}
public class Main {
public static void main(String[] args) {
byte[] buffer = new byte[4096];
IntByReference bufferSize = new IntByReference(buffer.length);
int bytesWritten = NativeExample.ne.decrypt("foo", buffer, bufferSize);
if (bytesWritten == 0 && bufferSize.getValue() > buffer.length) {
// buffer was too small for decrypted output
buffer = new byte[bufferSize.getValue()];
bytesWritten = NativeExample.ne.decrypt("foo", buffer, bufferSize);
}
String decrypted = new String(buffer, 0, bytesWritten);
System.out.println(decrypted);
}
}
如果您始终知道输出的大小,则可以简化调用以忽略更新的所需缓冲区大小,或者完全从C函数中删除它.
内容总结
以上是互联网集市为您收集整理的从本机代码返回`const char *`并在java中获取`String`全部内容,希望文章能够帮你解决从本机代码返回`const char *`并在java中获取`String`所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。