2a4e2b5378
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.
149 lines
4.5 KiB
Python
149 lines
4.5 KiB
Python
#!/usr/bin/env python
|
|
|
|
Import('env')
|
|
|
|
gdn_env = env.Clone()
|
|
|
|
gdn_env.add_source_files(env.modules_sources, "gd_native_library_editor.cpp")
|
|
gdn_env.add_source_files(env.modules_sources, "gdnative.cpp")
|
|
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, "nativescript/*.cpp")
|
|
|
|
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
|
|
|
|
def _spaced(e):
|
|
return e if e[-1] == '*' else e + ' '
|
|
|
|
def _build_gdnative_api_struct_header(api):
|
|
out = [
|
|
'/* THIS FILE IS GENERATED DO NOT EDIT */',
|
|
'#ifndef GODOT_GDNATIVE_API_STRUCT_H',
|
|
'#define GODOT_GDNATIVE_API_STRUCT_H',
|
|
'',
|
|
'#include <gdnative/gdnative.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',
|
|
'extern "C" {',
|
|
'#endif',
|
|
'',
|
|
'typedef struct godot_gdnative_api_struct {'
|
|
]
|
|
|
|
for funcname, funcdef in api['api'].items():
|
|
args = ', '.join(['%s%s' % (_spaced(t), n) for t, n in funcdef['arguments']])
|
|
out.append('\t%s(*%s)(%s);' % (_spaced(funcdef['return_type']), funcname, args))
|
|
|
|
out += [
|
|
'} godot_gdnative_api_struct;',
|
|
'',
|
|
'#ifdef __cplusplus',
|
|
'}',
|
|
'#endif',
|
|
'',
|
|
'#endif // GODOT_GDNATIVE_API_STRUCT_H',
|
|
''
|
|
]
|
|
return '\n'.join(out)
|
|
|
|
def _build_gdnative_api_struct_source(api):
|
|
out = [
|
|
'/* THIS FILE IS GENERATED DO NOT EDIT */',
|
|
'',
|
|
'#include <gdnative_api_struct.gen.h>',
|
|
'',
|
|
'extern const godot_gdnative_api_struct api_struct = {'
|
|
]
|
|
|
|
for funcname in api['api'].keys():
|
|
out.append('\t%s,' % funcname)
|
|
out.append('};\n')
|
|
|
|
return '\n'.join(out)
|
|
|
|
def build_gdnative_api_struct(target, source, env):
|
|
import json
|
|
from collections import OrderedDict
|
|
|
|
with open(source[0].path, 'r') as fd:
|
|
# Keep the json ordered
|
|
api = json.load(fd, object_pairs_hook=OrderedDict)
|
|
|
|
header, source = target
|
|
with open(header.path, 'w') as fd:
|
|
fd.write(_build_gdnative_api_struct_header(api))
|
|
with open(source.path, 'w') as fd:
|
|
fd.write(_build_gdnative_api_struct_source(api))
|
|
|
|
_, gensource = gdn_env.Command(['include/gdnative_api_struct.gen.h', 'gdnative_api_struct.gen.cpp'],
|
|
'gdnative_api.json', build_gdnative_api_struct)
|
|
gdn_env.add_source_files(env.modules_sources, [gensource])
|
|
|
|
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"])
|