Goal: Hey guys, I'm trying to use Discord's Game SDK in Java. Just a couple questions, thanks in advance for any help!
Question 1: When creating a JNA Structure, can I leave getters out? Example:
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;
}
}
Question 2: When creating a JNA Structure, can I load fields that I don't intend on using as Java Objects? Example:
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;
}
}
You might like taking a look at the many user mappings submitted to the JNA project, to get a general idea, but the answer to your questions:
You do not need getters. In fact, JNA's Structure
class requires that you declare every element as public, so they are unnecessary and redundant. They are sometimes included as convenience methods for things such as converting character arrays to strings, etc., but usually omitted.
You must include every element, or at least an equivalent byte size, of the native structure you're mapping. If they are inline structures, you would have to actually use the mappings. In the example above, they are mostly pointers (struct *
) so you can simply put a Pointer
object in their place to consume the same amount of memory.