当前位置: 首页 > 面试题库 >

如何调用使用JNA返回字符串的Delphi函数?

徐焱
2023-03-14
问题内容

我正在从Java程序的Delphi编译的*
.so文件中调用函数。经过研究后,JNA似乎是他的路要走。在深入研究一些复杂的Delphi代码之前,我尝试使用一些“
Hello World”代码,但是在获取由Delphi函数返回的字符串时遇到了麻烦。

Delphi代码(helloworld.pp):

library HelloWorldLib;

function HelloWorld(const myString: string): string; stdcall;
begin
  WriteLn(myString);
  Result := myString;
end;

exports HelloWorld;

begin
end.

我从命令行使用“ fpc -Mdelphi helloworld.pp编译它,生成 libhelloworld.so

现在我的Java课:

import com.sun.jna.Library;
import com.sun.jna.Native;

public class HelloWorld {
    public interface HelloWorldLibrary extends Library {
        HelloWorldLibrary INSTANCE = (HelloWorldLibrary) Native.loadLibrary("/full/path/to/libhelloworld.so", HelloWorldLibrary.class);

        String HelloWorld(String test);
    }

    public static void main(String[] args) {
        System.out.println(HelloWorldLibrary.INSTANCE.HelloWorld("QWERTYUIOP"));
    }
}

但是,当我运行此Java代码时,我得到:

# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f810318add2, pid=4088, tid=140192489072384
#
# JRE version: 7.0_10-b18
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.6-b04 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libhelloworld.so+0xbdd2]  HelloWorld+0x6fea

请注意,如果更改我的Delphi方法(和关联的Java接口)以返回一个硬编码的整数,则一切工作正常:我传递的字符串将被打印,并且我将整数按预期返回。

奇怪的是,如果Delphi方法返回一个char,我必须将JNA代理编写为返回一个字节,然后将其手动转换为char(如果我声明接口为返回char,则它会打印出一个垃圾字符)。

知道这里出了什么问题吗?

仅供参考,我正在使用Sun JDK 1.7.0_10-b18,JNA 3.5.1和Free Pascal
Compiler版本2.4.4-3.1使用64位Ubuntu 12.04。


问题答案:

Delphi或FreePascal
string是不能用作JNA类型的托管类型。所述JNA文档解释的Java
String被映射到的指针的8个字符的空终止阵列。用Delphi的说法是PAnsiChar

因此,您可以将Pascal代码中的输入参数从string更改为PAnsiChar

返回值存在更多问题。您将需要确定谁分配内存。分配它的人也必须释放它。

如果本机代码负责分配它,那么您需要堆分配以null终止的字符串。并返回指向它的指针。您还需要导出一个解除分配器,以便Java代码可以要求本机代码解除对堆分配的内存块的分配。

在Java代码中分配缓冲区通常更方便。然后将其传递给本机代码,并让其填写缓冲区的内容。这个堆栈溢出问题以Windows
API函数GetWindowText为例说明了该技术:如何使用JNI或JNA读取窗口标题?

使用Pascal的示例如下:

function GetText(Text: PAnsiChar; Len: Integer): Integer; stdcall;
const
  S: AnsiString = 'Some text value';
begin
  Result := Length(S)+1;//include null-terminator
  if Len>0 then
    StrPLCopy(Text, S, Len-1);
end;

在Java方面,考虑到我对Java完全一无所知,我想代码看起来像这样。

public interface MyLib extends StdCallLibrary {
    MyLib INSTANCE = (MyLib) Native.loadLibrary("MyLib", MyLib.class);
    int GetText(byte[] lpText, int len);
}

....

int len = User32.INSTANCE.GetText(null);
byte[] arr = new byte[len];
User32.INSTANCE.GetText(arr, len);
String Text = Native.toString(arr);


 类似资料:
  • 我找到了一些很好的SO链接(如何从异步回调函数返回值?以及从node.js中的回调函数返回值等),但它们并不是不能为我的问题提供解决方案。 我的问题:能够得到异步调用的结果,但我如何使用这个结果返回我的函数? 这里获取callBackResponse的值为true或false,并希望将该值用作:

  • 我有一个函数,当某些条件不满足时,它应该不返回任何内容(void)或字符串。 我也试过这句话。左(无效)

  • 问题内容: 如何从WebAssembly函数返回JavaScript字符串? 下列模块可以用C(++)编写吗? 另外:我可以将其传递给JS引擎进行垃圾回收吗? 问题答案: WebAssembly本身不支持字符串类型,它,而支撑件///值类型以及/用于存储。 这取决于您要执行的操作,但似乎直接访问缓冲区是最简单的: 如果您的模块具有功能,那么它将在实例化时执行。否则,您可能会调用一个导出,例如。 完

  • 我需要返回带有mongoDB聚合的字符串数组。我做了以下操作: 它返回: 有没有一种方法可以返回像这样的字符串数组: 非常感谢任何花时间帮助我的人。。 编辑 添加数据:

  • http://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c10849/Setting-a-System-Environment-Variable.htm 发送消息(HWND\u广播,WM\u设置更改,0,(LPARAM)“环境”); JNA和windows xp:调用以通知环境已更改 见链接:twall.github.com/jna/

  • 本文向大家介绍delphi字符串分隔函数用法实例,包括了delphi字符串分隔函数用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了delphi字符串分隔函数用法。分享给大家供大家参考。具体实现方法如下: 该实例可实现根据字符串Separator的表示将字符串s分隔为若干个字符串,存入rs字符串列表中,具体代码如下: 希望本文所述对大家的Delphi程序设计有所帮助。