[GDNative] added API struct wrapper generator
Previously functions of the GDNative API were accessed by letting the loader at load-time resolve the symbols. This causes troubles on Windows (...sigh...), so now the GDNative API isn't exported anymore. This means, that a library that wants to call a GDNative function needs to access it via a struct of pointers that's passed to it at right after the library was loaded. To make the usage easier, those function pointers in the struct can be wrapped in actual function in the global scope. This commit adds a generator for that wrapper code.
This commit is contained in:
parent
a848fa6cde
commit
2a4e2b5378
4 changed files with 71 additions and 54 deletions
|
@ -10,7 +10,6 @@ gdn_env.add_source_files(env.modules_sources, "register_types.cpp")
|
||||||
gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp")
|
gdn_env.add_source_files(env.modules_sources, "gdnative/*.cpp")
|
||||||
gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
|
gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
|
||||||
|
|
||||||
gdn_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
|
|
||||||
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
|
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
|
||||||
|
|
||||||
def _spaced(e):
|
def _spaced(e):
|
||||||
|
@ -25,6 +24,8 @@ def _build_gdnative_api_struct_header(api):
|
||||||
'#include <gdnative/gdnative.h>',
|
'#include <gdnative/gdnative.h>',
|
||||||
'#include <nativescript/godot_nativescript.h>',
|
'#include <nativescript/godot_nativescript.h>',
|
||||||
'',
|
'',
|
||||||
|
'#define GDNATIVE_API_INIT(options) do { extern const godot_gdnative_api_struct *_gdnative_wrapper_api_struct; _gdnative_wrapper_api_struct = options->api_struct; } while (0)',
|
||||||
|
'',
|
||||||
'#ifdef __cplusplus',
|
'#ifdef __cplusplus',
|
||||||
'extern "C" {',
|
'extern "C" {',
|
||||||
'#endif',
|
'#endif',
|
||||||
|
@ -81,7 +82,68 @@ _, gensource = gdn_env.Command(['include/gdnative_api_struct.gen.h', 'gdnative_a
|
||||||
'gdnative_api.json', build_gdnative_api_struct)
|
'gdnative_api.json', build_gdnative_api_struct)
|
||||||
gdn_env.add_source_files(env.modules_sources, [gensource])
|
gdn_env.add_source_files(env.modules_sources, [gensource])
|
||||||
|
|
||||||
if "platform" in env and env["platform"] in ["x11", "iphone"]:
|
|
||||||
env.Append(LINKFLAGS=["-rdynamic"])
|
|
||||||
|
|
||||||
env.use_ptrcall = True
|
env.use_ptrcall = True
|
||||||
|
|
||||||
|
|
||||||
|
def _build_gdnative_wrapper_code(api):
|
||||||
|
out = [
|
||||||
|
'/* THIS FILE IS GENERATED DO NOT EDIT */',
|
||||||
|
'',
|
||||||
|
'#include <gdnative/gdnative.h>',
|
||||||
|
'#include <nativescript/godot_nativescript.h>',
|
||||||
|
'',
|
||||||
|
'#include <gdnative_api_struct.gen.h>',
|
||||||
|
'',
|
||||||
|
'godot_gdnative_api_struct *_gdnative_wrapper_api_struct = 0;',
|
||||||
|
'',
|
||||||
|
'#ifdef __cplusplus',
|
||||||
|
'extern "C" {',
|
||||||
|
'#endif',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
|
||||||
|
for funcname, funcdef in api['api'].items():
|
||||||
|
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
|
||||||
|
out.append('%s %s(%s) {' % (_spaced(funcdef['return_type']), funcname, args))
|
||||||
|
|
||||||
|
args = ', '.join(['%s' % n for t, n in funcdef['arguments']])
|
||||||
|
|
||||||
|
return_line = '\treturn ' if funcdef['return_type'] != 'void' else '\t'
|
||||||
|
return_line += '_gdnative_wrapper_api_struct->' + funcname + '(' + args + ');'
|
||||||
|
|
||||||
|
out.append(return_line)
|
||||||
|
out.append('}')
|
||||||
|
out.append('')
|
||||||
|
|
||||||
|
out += [
|
||||||
|
'#ifdef __cplusplus',
|
||||||
|
'}',
|
||||||
|
'#endif'
|
||||||
|
]
|
||||||
|
|
||||||
|
return '\n'.join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def build_gdnative_wrapper_code(target, source, env):
|
||||||
|
import json
|
||||||
|
with open(source[0].path, 'r') as fd:
|
||||||
|
#Keep the json ordered
|
||||||
|
api = json.load(fd)
|
||||||
|
|
||||||
|
wrapper_file = target[0]
|
||||||
|
with open(wrapper_file.path, 'w') as fd:
|
||||||
|
fd.write(_build_gdnative_wrapper_code(api))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ARGUMENTS.get('gdnative_wrapper', False):
|
||||||
|
#build wrapper code
|
||||||
|
gdn_env.Command('gdnative_wrapper_code.gen.cpp', 'gdnative_api.json', build_gdnative_wrapper_code)
|
||||||
|
|
||||||
|
gd_wrapper_env = env.Clone()
|
||||||
|
gd_wrapper_env.Append(CPPPATH=['#modules/gdnative/include/'])
|
||||||
|
|
||||||
|
# I think this doesn't work on MSVC yet...
|
||||||
|
gd_wrapper_env.Append(CCFLAGS=['-fPIC'])
|
||||||
|
|
||||||
|
gd_wrapper_env.Library("#bin/gdnative_wrapper_code", ["#modules/gdnative/gdnative_wrapper_code.gen.cpp"])
|
||||||
|
|
|
@ -3334,7 +3334,7 @@
|
||||||
"arguments": [
|
"arguments": [
|
||||||
["godot_variant *", "p_self"],
|
["godot_variant *", "p_self"],
|
||||||
["const godot_string *", "p_method"],
|
["const godot_string *", "p_method"],
|
||||||
["const godot_variant *", "*p_args"],
|
["const godot_variant **", "p_args"],
|
||||||
["const godot_int", "p_argcount"],
|
["const godot_int", "p_argcount"],
|
||||||
["godot_variant_call_error *", "r_error"]
|
["godot_variant_call_error *", "r_error"]
|
||||||
]
|
]
|
||||||
|
@ -3889,7 +3889,7 @@
|
||||||
"return_type": "double",
|
"return_type": "double",
|
||||||
"arguments": [
|
"arguments": [
|
||||||
["const wchar_t *", "p_str"],
|
["const wchar_t *", "p_str"],
|
||||||
["const wchar_t *", "*r_end"]
|
["const wchar_t **", "r_end"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"godot_string_get_slice_count": {
|
"godot_string_get_slice_count": {
|
||||||
|
@ -4390,7 +4390,7 @@
|
||||||
"arguments": [
|
"arguments": [
|
||||||
["godot_method_bind *", "p_method_bind"],
|
["godot_method_bind *", "p_method_bind"],
|
||||||
["godot_object *", "p_instance"],
|
["godot_object *", "p_instance"],
|
||||||
["const void *", "*p_args"],
|
["const void **", "p_args"],
|
||||||
["void *", "p_ret"]
|
["void *", "p_ret"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -4399,7 +4399,7 @@
|
||||||
"arguments": [
|
"arguments": [
|
||||||
["godot_method_bind *", "p_method_bind"],
|
["godot_method_bind *", "p_method_bind"],
|
||||||
["godot_object *", "p_instance"],
|
["godot_object *", "p_instance"],
|
||||||
["const godot_variant *", "*p_args"],
|
["const godot_variant **", "p_args"],
|
||||||
["const int", "p_arg_count"],
|
["const int", "p_arg_count"],
|
||||||
["godot_variant_call_error *", "p_call_error"]
|
["godot_variant_call_error *", "p_call_error"]
|
||||||
]
|
]
|
||||||
|
|
|
@ -34,18 +34,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GDAPI_BUILT_IN
|
|
||||||
#define GDAPI_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if defined(GDAPI_EXPORT)
|
|
||||||
#define GDCALLINGCONV
|
#define GDCALLINGCONV
|
||||||
#define GDAPI __declspec(dllexport) GDCALLINGCONV
|
#define GDAPI GDCALLINGCONV
|
||||||
#else
|
|
||||||
#define GDCALLINGCONV
|
|
||||||
#define GDAPI __declspec(dllimport) GDCALLINGCONV
|
|
||||||
#endif
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include "TargetConditionals.h"
|
#include "TargetConditionals.h"
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
|
|
|
@ -36,42 +36,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GDAPI_BUILT_IN
|
|
||||||
#define GDAPI_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#if defined(GDAPI_EXPORT)
|
|
||||||
#define GDCALLINGCONV
|
|
||||||
#define GDAPI __declspec(dllexport) GDCALLINGCONV
|
|
||||||
#else
|
|
||||||
#define GDCALLINGCONV
|
|
||||||
#define GDAPI __declspec(dllimport) GDCALLINGCONV
|
|
||||||
#endif
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
#include "TargetConditionals.h"
|
|
||||||
#if TARGET_OS_IPHONE
|
|
||||||
#define GDCALLINGCONV __attribute__((visibility("default")))
|
|
||||||
#define GDAPI GDCALLINGCONV
|
|
||||||
#elif TARGET_OS_MAC
|
|
||||||
#define GDCALLINGCONV __attribute__((sysv_abi))
|
|
||||||
#define GDAPI GDCALLINGCONV
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define GDCALLINGCONV __attribute__((sysv_abi, visibility("default")))
|
|
||||||
#define GDAPI GDCALLINGCONV
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is for libraries *using* the header, NOT GODOT EXPOSING STUFF!!
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define GDN_EXPORT __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define GDN_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GODOT_METHOD_RPC_MODE_DISABLED,
|
GODOT_METHOD_RPC_MODE_DISABLED,
|
||||||
GODOT_METHOD_RPC_MODE_REMOTE,
|
GODOT_METHOD_RPC_MODE_REMOTE,
|
||||||
|
|
Loading…
Reference in a new issue