Linux,JNA:关于liblo第二个方法调用的UnsatisfiedLinkError

问题描述 投票:1回答:2

我喜欢用java来控制'sooperlooper',这是一个声音。这使用OSC协议。首先尝试的是Java OSC lib,但这没有做任何事情。现在我正在尝试JNA来包装liblo.so

我试图在JAVA中复制的程序非常简单(当然使用来自“record”的不同命令):

static lo_address addr;

int main(int argc, char *argv[])
{
        addr = lo_address_new(<IP>, "9951");
        lo_send(addr, "/sl/-1/down", "s", "record");
}

失败方法的C声明是(https://github.com/radarsat1/liblo/blob/master/lo/lo.h.in):

int lo_send(lo_address targ, const char *path, const char *type, ...);

如果我理解正确,lo_address是在别处声明的一些void指针类型。我的库界面是:

public interface LibLo extends Library {
    Pointer lo_address_new(String host, String port);
    int lo_send(Pointer address, String command, String a, String... params);
}

我的来电代码是这样的:

System.setProperty("jna.debug_load", "true");
System.setProperty("jna.debug_load.jna", "true");
LibLo libLo = Native.loadLibrary("liblo", LibLo.class);

Pointer pointer = libLo.lo_address_new(<IP>, "9951");
libLo.lo_send(pointer, "/sl/-1/down","s", "record");

它完美地通过lo_address_new调用。 '指针'确实有一些价值。我认为我的论点是正确的。我发现即使是不正确的参数,它也会通过lo_address_new调用。

我的标准是:

...
Found library 'liblo' at /usr/lib/x86_64-linux-gnu/liblo.so.7.3.0
Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'lo_send': /usr/lib/x86_64-linux-gnu/liblo.so.7.3.0: undefined symbol: lo_send
    at com.sun.jna.Function.<init>(Function.java:245)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:566)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:542)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:528)
    at com.sun.jna.Library$Handler.invoke(Library.java:228)
    at com.sun.proxy.$Proxy0.lo_send(Unknown Source)
    at nl.ronaldteune.coverdownloader.Main.main(Main.java:30)

关于UnsatisfiedLinkError的其他问题指出了更彻底的问题。当用vim打开lib时我找不到'lo_send',但我可以找到lo_send_message - 但它更低级别。但是,我认为我的C程序使用相同的lib(使用-llo编译)并且它没有运行问题。所以......我被困住了。有谁知道如何进一步调试?

java c jna
2个回答
1
投票

您无法将lo_send()映射到JNA(并且它不会出现在您的vim输出中),因为它是一个宏:

#define lo_send(targ, path, types...) \
        lo_send_internal(targ, __FILE__, __LINE__, path, types, \
             LO_MARKER_A, LO_MARKER_B)

理论上,你可以映射lo_send_internal(),但它的源代码注释说:

/* Don't call lo_send_internal directly, use lo_send, a macro wrapping this
 * function with appropriate values for file and line */

这是有意义的,因为它需要在编译时知道源代码__FILE____LINE__数,并且你在JNA中为这些值做的任何hack都必须假设你有正确的源代码用于编译你的二进制.so。你还需要标记,但它们至少是常量,十六进制代码中有趣的单词。

您可能只需要为文件和行输入虚拟值以使代码正常工作,但除此之外,调用lo_send()的C包装函数看起来就像是这种情况下的最佳解决方法。


1
投票

好的,我解决了它...使用包装器lib:

#include <lo/lo.h>
static lo_address addr;

lo_address slGetAddress() {
        return lo_address_new("IP", "9951");

}

void slSendFull(lo_address addr, const char *command) {
        lo_send(addr, "/sl/-1/down", "s", command);
}

void slSendSimple(const char *command) {
        addr = slGetAddress();
        lo_send(addr, "/sl/-1/down", "s", command);
}

和这个编译脚本:

#!/bin/bash
# sudo ln -s /usr/lib/arm-linux-gnueabihf/liblo.so.7 /usr/local/lib/liblo.so
# sudo ln -s /usr/lib/x86_64-linux-gnu/liblo.so.7 /usr/local/lib/liblo.so

gcc -c -Wall -O2 -fPIC lowrapper.c -llo
ld -shared lowrapper.o /usr/local/lib/liblo.so -o lowrapper.so
sudo cp lowrapper.so /usr/local/lib/

它现在正在运作。仍然对真正的答案感兴趣,但不再匆忙:)

© www.soinside.com 2019 - 2024. All rights reserved.