JNA:在 Spotify API 中找不到 C 方法

发布于 2024-10-19 08:53:08 字数 3002 浏览 1 评论 0原文

我试图了解 JNA 的工作原理,因此我决定使用 spotify API (libspotify 0.0.7)。我设法正确加载我的 dll,但看起来我的代码没有找到 API 中定义的任何方法。

这是我的测试代码:

public class Test { 
    static{
        System.loadLibrary("libspotify");
    }

    public interface LibSpotify extends Library {
        public static class sp_artist extends Structure{
            public String name;
            public boolean isLoaded;
            public int refCount;
        };

        LibSpotify INSTANCE = (LibSpotify)Native.loadLibrary("libspotify", LibSpotify.class);

        public String sp_artist_name(sp_artist artist);
    }

    public static void main(String[] args){
        LibSpotify ls = LibSpotify.INSTANCE;

        LibSpotify.sp_artist artist = new LibSpotify.sp_artist(){
            String name = "thename";
            boolean isLoaded = false;
            int refCount = 0;
        };

        ls.sp_artist_name(artist);
    }
}

这是我尝试访问的方法的 C 声明,在 libspotify 的 api.h 中:

/**
 * Return name of artist
 *
 * @param[in]   artist     Artist object
 *
 * @return                 Name of artist.
 *                         Returned string is valid as long as the artist object stays allocated
 *                         and no longer than the next call to sp_session_process_events()
 */
SP_LIBEXPORT(const char *) sp_artist_name(sp_artist *artist);

这是我的 StackTrace:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'sp_artist_name': The specified procedure could not be found.

    at com.sun.jna.Function.<init>(Function.java:129)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:250)
    at com.sun.jna.Library$Handler.invoke(Library.java:191)
    at $Proxy0.sp_artist_name(Unknown Source)
    at com.nbarraille.jspotify.main.Test2.main(Test2.java:33)

我的 DLL 是否有问题,或者我做错了什么?

顺便说一下,我无法访问C中sp_artist结构的定义,我只是根据API提供的方法重建了它,这可能是问题所在吗?:

/**
 * @defgroup artist Artist subsystem
 * @{
 */

/**
 * Return name of artist
 *
 * @param[in]   artist     Artist object
 *
 * @return                 Name of artist.
 *                         Returned string is valid as long as the artist object stays allocated
 *                         and no longer than the next call to sp_session_process_events()
 */
SP_LIBEXPORT(const char *) sp_artist_name(sp_artist *artist);

/**
 * Check if the artist object is populated with data
 *
 * @param[in]   artist     An artist object
 *
 * @return                 True if metadata is present, false if not
 *
 */
SP_LIBEXPORT(bool) sp_artist_is_loaded(sp_artist *artist);


/**
 * Increase the reference count of a artist
 *
 * @param[in]   artist       The artist object
 */
SP_LIBEXPORT(void) sp_artist_add_ref(sp_artist *artist);

/**
 * Decrease the reference count of a artist
 *
 * @param[in]   artist       The artist object
 */
SP_LIBEXPORT(void) sp_artist_release(sp_artist *artist);

/** @} */

谢谢!

I was trying to learn how JNA works, so I decided to use the spotify API (libspotify 0.0.7). I managed to load my dll correctly, but then it looks like my code is not finding any of the method defined in the API.

Here is my test code:

public class Test { 
    static{
        System.loadLibrary("libspotify");
    }

    public interface LibSpotify extends Library {
        public static class sp_artist extends Structure{
            public String name;
            public boolean isLoaded;
            public int refCount;
        };

        LibSpotify INSTANCE = (LibSpotify)Native.loadLibrary("libspotify", LibSpotify.class);

        public String sp_artist_name(sp_artist artist);
    }

    public static void main(String[] args){
        LibSpotify ls = LibSpotify.INSTANCE;

        LibSpotify.sp_artist artist = new LibSpotify.sp_artist(){
            String name = "thename";
            boolean isLoaded = false;
            int refCount = 0;
        };

        ls.sp_artist_name(artist);
    }
}

Here is the C declaration of the method I try to access, in the api.h of libspotify:

/**
 * Return name of artist
 *
 * @param[in]   artist     Artist object
 *
 * @return                 Name of artist.
 *                         Returned string is valid as long as the artist object stays allocated
 *                         and no longer than the next call to sp_session_process_events()
 */
SP_LIBEXPORT(const char *) sp_artist_name(sp_artist *artist);

And here is my StackTrace:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'sp_artist_name': The specified procedure could not be found.

    at com.sun.jna.Function.<init>(Function.java:129)
    at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:250)
    at com.sun.jna.Library$Handler.invoke(Library.java:191)
    at $Proxy0.sp_artist_name(Unknown Source)
    at com.nbarraille.jspotify.main.Test2.main(Test2.java:33)

Is there a problem with my DLL, or am I doing something wrong?

By the way, I don't have access to the definition of the sp_artist structure in C, I just reconstructed it based on the methods offered by the API, could it be the problem?:

/**
 * @defgroup artist Artist subsystem
 * @{
 */

/**
 * Return name of artist
 *
 * @param[in]   artist     Artist object
 *
 * @return                 Name of artist.
 *                         Returned string is valid as long as the artist object stays allocated
 *                         and no longer than the next call to sp_session_process_events()
 */
SP_LIBEXPORT(const char *) sp_artist_name(sp_artist *artist);

/**
 * Check if the artist object is populated with data
 *
 * @param[in]   artist     An artist object
 *
 * @return                 True if metadata is present, false if not
 *
 */
SP_LIBEXPORT(bool) sp_artist_is_loaded(sp_artist *artist);


/**
 * Increase the reference count of a artist
 *
 * @param[in]   artist       The artist object
 */
SP_LIBEXPORT(void) sp_artist_add_ref(sp_artist *artist);

/**
 * Decrease the reference count of a artist
 *
 * @param[in]   artist       The artist object
 */
SP_LIBEXPORT(void) sp_artist_release(sp_artist *artist);

/** @} */

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玉环 2024-10-26 08:53:08

终于通过使用 Dependency Walker 打开 libspotify.dll 找到了解决方案:
编译器向方法名称添加了一些额外信息(下划线前缀和@4或@8后缀)。

我必须:

  • 创建 FunctionMapper 的实现,根据真实名称重命名我的所有方法(在 Dependency Walker 中可用)
  • 使用选项映射中此映射器的实例实例化我的库。

I finally found the solution by opening the libspotify.dll with Dependency Walker:
The compiler added some extra information to the method name (a underscore prefix and a @4 or @8 suffix).

I had to:

  • Create an implementation of FunctionMapper that renamed all my methods according to the real names (available in Dependency Walker)
  • Instantiate my Library with an instance of this mapper in the options map.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文