一般 JNA 问题(Discord 游戏 SDK (C) -> Java)

General JNA Questions (Discord Game SDK (C) -> Java)

目标: 大家好,我正在尝试在 Java 中使用 Discord 的游戏 SDK。只是几个问题,在此先感谢您的帮助!

问题 1: 创建 JNA 结构时,我可以不使用吸气剂吗?示例:


import com.sun.jna.Callback;
import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/*
struct IDiscordCore {
    void (*destroy)(struct IDiscordCore* core);
    enum EDiscordResult (*run_callbacks)(struct IDiscordCore* core);
    void (*set_log_hook)(struct IDiscordCore* core, enum EDiscordLogLevel min_level, void* hook_data, void (*hook)(void* hook_data, enum EDiscordLogLevel level, const char* message));
    struct IDiscordApplicationManager* (*get_application_manager)(struct IDiscordCore* core);
    struct IDiscordUserManager* (*get_user_manager)(struct IDiscordCore* core);
    struct IDiscordImageManager* (*get_image_manager)(struct IDiscordCore* core);
    struct IDiscordActivityManager* (*get_activity_manager)(struct IDiscordCore* core);
    struct IDiscordRelationshipManager* (*get_relationship_manager)(struct IDiscordCore* core);
    struct IDiscordLobbyManager* (*get_lobby_manager)(struct IDiscordCore* core);
    struct IDiscordNetworkManager* (*get_network_manager)(struct IDiscordCore* core);
    struct IDiscordOverlayManager* (*get_overlay_manager)(struct IDiscordCore* core);
    struct IDiscordStorageManager* (*get_storage_manager)(struct IDiscordCore* core);
    struct IDiscordStoreManager* (*get_store_manager)(struct IDiscordCore* core);
    struct IDiscordVoiceManager* (*get_voice_manager)(struct IDiscordCore* core);
    struct IDiscordAchievementManager* (*get_achievement_manager)(struct IDiscordCore* core);
};
 */
public class IDiscordCore extends Structure {

    public interface OnDestroy extends Callback {
        void accept(IDiscordCore core);
    }

    public interface OnCallbacks extends Callback {
        EDiscordResult accept(IDiscordCore core);
    }

    private static final List<String> FIELD_ORDER = Collections.unmodifiableList(Arrays.asList(
            "destroy", "run_callbacks", "set_log_hook"
    ));

    public OnDestroy destroy;
    public OnCallbacks run_callbacks;
    public Object set_log_hook;

    @Override
    public boolean equals(Object o) {
        if(this == o)
            return true;
        if(!(o instanceof IDiscordCore))
            return false;
        IDiscordCore that = (IDiscordCore) o;
        return Objects.equals(destroy, that.destroy)
                && Objects.equals(run_callbacks, that.run_callbacks)
                && Objects.equals(set_log_hook, that.set_log_hook) ;
    }

    @Override
    public int hashCode() {
        return Objects.hash(destroy, run_callbacks, set_log_hook);
    }

    @Override
    protected List<String> getFieldOrder() {
        return FIELD_ORDER;
    }

}

问题 2: 创建 JNA 结构时,我可以加载不打算用作 Java 对象的字段吗?示例:


import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/*
//typedef int64_t DiscordClientId;
//typedef void* IDiscordCoreEvents;
struct DiscordCreateParams {
    DiscordClientId client_id;
    uint64_t flags;
    IDiscordCoreEvents* events;
    void* event_data;
    IDiscordApplicationEvents* application_events;
    DiscordVersion application_version;
    struct IDiscordUserEvents* user_events;
    DiscordVersion user_version;
    IDiscordImageEvents* image_events;
    DiscordVersion image_version;
    struct IDiscordActivityEvents* activity_events;
    DiscordVersion activity_version;
    struct IDiscordRelationshipEvents* relationship_events;
    DiscordVersion relationship_version;
    struct IDiscordLobbyEvents* lobby_events;
    DiscordVersion lobby_version;
    struct IDiscordNetworkEvents* network_events;
    DiscordVersion network_version;
    struct IDiscordOverlayEvents* overlay_events;
    DiscordVersion overlay_version;
    IDiscordStorageEvents* storage_events;
    DiscordVersion storage_version;
    struct IDiscordStoreEvents* store_events;
    DiscordVersion store_version;
    struct IDiscordVoiceEvents* voice_events;
    DiscordVersion voice_version;
    struct IDiscordAchievementEvents* achievement_events;
    DiscordVersion achievement_version;
};
 */
public class DiscordCreateParams extends Structure {

    public long client_id;

    public String flags;

    public Object events;

    public Object event_data;

    public Object application_events, application_version, user_events, user_version, image_events, image_version, activity_events, activity_version, relationship_events, relationship_version, lobby_events, lobby_version, network_events, network_version, overlay_events, overlay_version, storage_events, storage_version, store_events, store_version, voice_events, voice_version, achievement_events, achievement_version;

    private static final List<String> FIELD_ORDER = Collections.unmodifiableList(Arrays.asList("client_id", "flags", "events", "event_data", "application_events", "application_version", "user_events", "user_version", "image_events", "image_version", "activity_events", "activity_version", "relationship_events", "relationship_version", "lobby_events", "lobby_version", "network_events", "network_version", "overlay_events", "overlay_version", "storage_events", "storage_version", "store_events", "store_version", "voice_events", "voice_version", "achievement_events", "achievement_version"));

    @Override
    public boolean equals(Object o) {
        if(this == o)
            return true;
        if(!(o instanceof DiscordCreateParams))
            return false;
        DiscordCreateParams that = (DiscordCreateParams) o;
        return Objects.equals(client_id, that.client_id) && Objects.equals(flags, that.flags) && Objects.equals(events, that.events) && Objects.equals(event_data, that.event_data) && Objects.equals(application_events, that.application_events) && Objects.equals(application_version, that.application_version) && Objects.equals(user_events, that.user_events) && Objects.equals(user_version, that.user_version) && Objects.equals(image_events, that.image_events) && Objects.equals(image_version, that.image_version) && Objects.equals(activity_events, that.activity_events) && Objects.equals(activity_version, that.activity_version) && Objects.equals(relationship_events, that.relationship_events) && Objects.equals(relationship_version, that.relationship_version) && Objects.equals(lobby_events, that.lobby_events) && Objects.equals(lobby_version, that.lobby_version) && Objects.equals(network_events, that.network_events) && Objects.equals(network_version, that.network_version) && Objects.equals(overlay_events, that.overlay_events) && Objects.equals(overlay_version, that.overlay_version) && Objects.equals(storage_events, that.storage_events) && Objects.equals(store_version, that.store_version) && Objects.equals(voice_events, that.voice_events) && Objects.equals(voice_version, that.voice_version) && Objects.equals(achievement_events, that.achievement_events) && Objects.equals(achievement_version, that.achievement_version);
    }

    @Override
    public int hashCode() {
        return Objects.hash(client_id, flags, events, event_data, application_events, application_version, user_events, user_version, image_events, image_version, activity_events, activity_version, relationship_events, relationship_version, lobby_events, lobby_version, network_events, network_version, overlay_events, overlay_version, storage_events, storage_version, store_events, store_version, voice_events, voice_version, achievement_events, achievement_version);
    }

    @Override
    protected List<String> getFieldOrder() {
        return FIELD_ORDER;
    }

}

您可能想看一下提交给 JNA 项目的许多用户映射,以获得一个大概的概念,但是您的问题的答案:

  • 你不需要吸气剂。事实上,JNA 的 Structure class 要求您将每个元素声明为 public,因此它们是不必要的和多余的。它们有时作为将字符数组转换为字符串等的便捷方法包含在内,但通常被省略。

  • 您必须包含要映射的本机结构的每个元素,或至少包含等效字节大小。如果它们是内联结构,则您必须实际使用映射。在上面的示例中,它们主要是指针 (struct *),因此您可以简单地在它们的位置放置一个 Pointer 对象来消耗相同数量的内存。