GDNative
마지막으로 3.0 출시에 가장 빛나는 추가 요소입니다: GDNative는 Godot를 다시 컴파일 하지 않아도 (심지어 재시작을 하지 않아도) C++에서 스크립트할 수 있습니다.
모든 C++버전을 사용할 수 있고, 내부 C API Bridge를 사용해서 생성한 공유 라이브러리의 컴파일러 브랜드와 버전을 완벽하게 혼합할 수 있습니다.
This language is the best choice for performance and does not need to be used throughout an entire game, as other parts can be written in GDScript or Visual Script. However, the API is clear and easy to use as it resembles, mostly, Godot's actual C++ API.
더 많은 언어는 GDNative 인터페이스를 통해 사용할 수 있지만 이 인터페이스에 대한 공식적인 지원은 없습니다.
직접 만들어 보자
소개
이 가이드에서는 GDNative 모듈을 만드는 데 필요한 최소한의 정보를 소개합니다. 이것이 GDNative의 세계로 들어가는 출발점이 될 것입니다. 이 튜토리얼의 내용을 이해하면 이후에 올 모든 내용을 이해하는 데 도움이됩니다.
시작하기 전에 GDNative-demos 저장소 에서 아래에 설명 된 예제 개체에 소스 코드를 다운로드 할 수 있습니다 .
이 예제 프로젝트에는 컴파일을 좀 더 쉽게하는 SConstruct 파일도 포함되어 있지만이 자습서에서는 프로세스를 이해하기 위해 직접 작업을 수행합니다.
GDNative 는 PluginScript 또는 ARVRInterfaceGDNative 와 같은 인터페이스를 사용하여 Godot에 여러 유형의 추가 항목을 만드는 데 사용할 수 있습니다 . 이 튜토리얼에서는 NativeScript 모듈을 만드는 방법을 살펴볼 것입니다. NativeScript를 사용하면 GDScript 파일을 작성하는 것과 유사한 방식으로 C 또는 C++로 논리를 작성할 수 있습니다. 이 GDScript에 해당하는 C를 만들 것입니다:
extends Reference
var data
func _ready():
data = "World from GDScript!"
func get_data():
return data
향후 가이드에서는 다른 유형의 GDNative 모듈에 중점을두고 각 모듈을 언제 어떻게 사용하는지 설명합니다.
전제 조건
시작하기 전에 몇 가지가 필요합니다.
- 대상 버전에 대한 Godot 실행 파일.
- C 컴파일러. Linux에서는 gcc또는 clang패키지 관리자에서 설치 합니다. macOS에서는 Mac App Store에서 Xcode를 설치할 수 있습니다. Windows에서는 Visual Studio 2015 이상 또는 MinGW-w64를 사용할 수 있습니다.
- godot_headers 저장소 의 Git 복제본 : GDNative에 노출 된 Godot의 공용 API에 대한 C 헤더입니다.
GDNative 예제 프로젝트를위한 전용 폴더를 만들고 해당 폴더에서 터미널을 열고 다음을 실행하는 것이 좋습니다.
WARNING |
버전에 맞게 해당 태그( |
Our C source
다음 구조로 디렉토리를 만들자.
+ <your development folder>
+ godot_headers
- <lots of files here>
+ simple
+ bin
- libsimple.dll/so/dylib
- libsimple.gdnlib
- simple.gdns
main.tscn
project.godot
+ src
- simple.c
Godot를 열고 godot_headers
Git 클론 과 함께 simple
이라는 새 프로젝트를 만듭니다. 그러면 simple
폴더와 project.godot
파일 이 생성 됩니다. 그런 다음 수동으로 src
폴더 옆에 simple
폴더를 만들고 bin
폴더에 하위 simple
폴더를 만듭니다.
simple.c
파일에 포함 된 내용을 살펴 보는 것으로 시작하겠습니다 . 이제 여기 예제에서는 간단하게 유지하기 위해 헤더없이 단일 C 소스 파일을 만듭니다. 더 큰 프로젝트를 작성하기 시작하면 프로젝트를 여러 파일로 나누는 것이 좋습니다. 그러나 이는이 튜토리얼의 범위를 벗어납니다.
우리는 소스 코드를 조금씩 살펴볼 것이므로 아래의 모든 부분을 하나의 큰 파일로 모아야합니다. 추가 할 때마다 각 섹션에 대해 설명합니다.
#include <gdnative_api_struct.gen.h>
#include <string.h>
const godot_gdnative_core_api_struct *api = NULL;
const godot_gdnative_ext_nativescript_api_struct *nativescript_api = NULL;
위의 코드에는 GDNative API 구조체 헤더와 문자열 작업에 사용할 표준 헤더가 포함되어 있습니다. 그런 다음 두 개의 다른 구조체에 대한 두 개의 포인터를 정의합니다. GDNative는 기본 Godot 실행 파일로 다시 호출하기위한 대규모 기능 모음을 지원합니다. 모듈이 이러한 함수에 액세스 할 수 있도록 GDNative는 애플리케이션에 이러한 모든 함수에 대한 포인터가 포함 된 구조체를 제공합니다.
이 구현을 모듈 식으로 유지하고 쉽게 확장 할 수 있도록 핵심 기능은 "core"API 구조체를 통해 직접 사용할 수 있지만 추가 함수에는 확장을 통해 액세스 할 수있는 자체 "GDNative 구조체"가 있습니다.
이 예에서는 이러한 확장 중 하나에 액세스하여 특히 NativeScript에 필요한 기능에 액세스합니다.
NativeScript는 Godot의 다른 스크립트처럼 작동합니다. NativeScript API는 다소 낮은 수준이기 때문에 라이브러리가 GDScript와 같은 다른 스크립팅 시스템보다 많은 것을 더 자세하게 지정해야합니다. NativeScript 인스턴스가 생성되면 라이브러리에서 제공 한 생성자가 호출됩니다. 해당 인스턴스가 파괴되면 지정된 소멸자가 실행됩니다.
void *simple_constructor(godot_object *p_instance, void *p_method_data);
void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data);
godot_variant simple_get_data(godot_object *p_instance, void *p_method_data,
void *p_user_data, int p_num_args, godot_variant **p_args);
객체에 대해 구현할 함수에 대한 전방 선언입니다. 생성자와 소멸자가 필요합니다. 또한 객체에는 get_data
.
다음은 동적 라이브러리가로드 될 때 Godot가 호출 할 첫 번째 진입 점입니다. 이러한 메서드는 모두 접두어 godot_
(나중에 변경할 수 있음)와 이름이 붙습니다. gdnative_init
동적 라이브러리를 초기화하는 함수입니다. Godot는 API 구조에 대한 포인터 중에서 유용하다고 생각되는 다양한 정보를 포함하는 구조에 대한 포인터를 제공합니다.
추가 API 구조의 경우 확장 배열을 반복하고 확장 유형을 확인해야합니다.
void GDN_EXPORT godot_gdnative_init(godot_gdnative_init_options *p_options) {
api = p_options->api_struct;
// Now find our extensions.
for (int i = 0; i < api->num_extensions; i++) {
switch (api->extensions[i]->type) {
case GDNATIVE_EXT_NATIVESCRIPT: {
nativescript_api = (godot_gdnative_ext_nativescript_api_struct *)api->extensions[i];
}; break;
default: break;
}
}
}
다음 gdnative_terminate
은 라이브러리가 언로드되기 전에 호출되는 것입니다. Godot는 더 이상 객체가 사용하지 않을 때 라이브러리를 언로드합니다. 여기에서 필요한 모든 정리를 수행 할 수 있습니다. 이 예에서는 단순히 API 포인터를 지울 것입니다.
void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *p_options) {
api = NULL;
nativescript_api = NULL;
}
마지막으로, nativescript_init
오늘 우리에게 필요한 가장 중요한 기능이 있습니다. 이 함수는 GDNative 라이브러리로드의 일부로 Godot에 의해 호출되며 사용 가능한 개체를 엔진에 다시 전달합니다.
void GDN_EXPORT godot_nativescript_init(void *p_handle) {
godot_instance_create_func create = { NULL, NULL, NULL };
create.create_func = &simple_constructor;
godot_instance_destroy_func destroy = { NULL, NULL, NULL };
destroy.destroy_func = &simple_destructor;
nativescript_api->godot_nativescript_register_class(p_handle, "Simple", "Reference", create, destroy);
godot_instance_method get_data = { NULL, NULL, NULL };
get_data.method = &simple_get_data;
godot_method_attributes attributes = { GODOT_METHOD_RPC_MODE_DISABLED };
nativescript_api->godot_nativescript_register_method(p_handle, "Simple", "get_data",
attributes, get_data);
}
먼저를 호출하여 구현 된 클래스를 엔진에 알립니다 nativescript_register_class
.
- 여기서 첫 번째 매개 변수는 우리에게 주어진 핸들 포인터입니다.
- 두 번째는 객체 클래스의 이름입니다.
- 세 번째는 우리가 '상속'하는 Godot의 객체 유형입니다. 이것은 진정한 상속은 아니지만 충분히 가깝습니다.
- 마지막으로 네 번째와 다섯 번째 매개 변수는 생성자와 소멸자에 대한 설명입니다.
그런 다음 nativescript_register_method
클래스의 각 메서드를 호출 하여 메서드 (이 경우 하나의 메서드)에 대해 Godot에 알립니다. 우리의 경우에는 get_data
.
- 첫 번째 매개 변수는 다시 핸들 포인터입니다.
- 두 번째는 다시 등록하려는 객체 클래스의 이름입니다.
- 세 번째는 GDScript에 알려진 함수의 이름입니다.
- 네 번째는 속성 설정입니다 (가능한 값은
godot_method_rpc_mode
열거 형 참조godot_headers/nativescript/godot_nativescript.h
). - 다섯 번째이자 마지막 매개 변수는 메서드가 호출 될 때 호출 할 함수에 대한 설명입니다.
설명 구조체 instance_method
는
- 함수 자체에 대한 함수 포인터를 첫 번째 필드로 포함합니다. 이 구조체의 다른 두 필드는 메서드 별 사용자 데이터를 지정하기위한 것입니다.
- 두 번째는
method_data
모든 함수 호출에서p_method_data
인수 로 전달 되는 필드입니다. 이것은 여러 다른 스크립트 클래스에서 다른 메서드에 대해 하나의 함수를 재사용하는 데 유용합니다.method_data
값이 필요 해제 할 것을 메모리에 대한 포인터이며, 세 번째free_func
필드에 해당 메모리를 해제하는 함수에 대한 포인터를 포함 할 수 있습니다. 이 자유 함수는 스크립트 자체 (인스턴스가 아님)가 언로드 될 때 호출됩니다 (일반적으로 라이브러리 언로드 시간에).
이제 객체의 기능에 대한 작업을 시작할 때입니다. 먼저 GDNative 클래스 인스턴스의 멤버 데이터를 저장하는 데 사용하는 구조를 정의합니다.
그런 다음 생성자를 정의합니다. 생성자에서 우리가하는 일은 구조에 메모리를 할당하고 데이터로 채우는 것입니다. Godot의 메모리 함수를 사용하여 메모리를 추적 한 다음 새 구조에 대한 포인터를 반환합니다. 이 포인터는 여러 개체가 인스턴스화되는 경우 인스턴스 식별자 역할을합니다.
이 포인터는 객체와 관련된 함수에라는 매개 변수로 전달되며 p_user_data
인스턴스를 식별하고 멤버 데이터에 액세스하는 데 사용할 수 있습니다.
void *simple_constructor(godot_object *p_instance, void *p_method_data) {
user_data_struct *user_data = api->godot_alloc(sizeof(user_data_struct));
strcpy(user_data->data, "World from GDNative!");
return user_data;
}
우리의 소멸자는 Godot가 우리의 개체를 완료하고 인스턴스의 멤버 데이터를 해제 할 때 호출됩니다.
void simple_destructor(godot_object *p_instance, void *p_method_data, void *p_user_data) {
api->godot_free(p_user_data);
}
마지막으로 get_data
기능 을 구현 합니다. 데이터는 항상 변형으로 전송되고 반환되므로 데이터 (문자열)를 반환하려면 먼저 C 문자열을 Godot 문자열 객체로 변환 한 다음 해당 문자열 객체를 반환하는 변형에 복사해야합니다.
godot_variant simple_get_data(godot_object *p_instance, void *p_method_data,
void *p_user_data, int p_num_args, godot_variant **p_args) {
godot_string data;
godot_variant ret;
user_data_struct *user_data = (user_data_struct *)p_user_data;
api->godot_string_new(&data);
api->godot_string_parse_utf8(&data, user_data->data);
api->godot_variant_new_string(&ret, &data);
api->godot_string_destroy(&data);
return ret;
}
문자열은 Godot에서 힙 할당되므로 메모리를 해제하는 소멸자가 있습니다. 소멸자의 이름은 godot_TYPENAME_destroy
. Variant가 String으로 생성되면 String을 참조합니다. 이는 참조 횟수를 줄이기 위해 원래 문자열을 "파괴"할 수 있음을 의미합니다. 이것이 발생하지 않으면 ref-count가 0이 아니고 메모리가 할당 해제되지 않으므로 String 메모리가 누출됩니다. 반환 된 변형은 Godot에 의해 자동으로 파괴됩니다.
INFORMATION |
더 복잡한 작업에서는 할당을 취소해야하는 값과 그렇지 않은 값을 추적하는 것이 혼란 스러울 수 있습니다. 일반적으로 |
컴파일링(Compiling)
이제 소스 코드를 컴파일해야합니다. 언급했듯이 GitHub의 예제 프로젝트에는 모든 작업을 수행하는 SCons 구성이 포함되어 있지만 여기 튜토리얼에서는 컴파일러를 직접 호출 할 것입니다.
위에서 제안한 폴더 구조를 고수한다고 가정하면 폴더에서 터미널 세션을 열고 src
거기에서 명령을 실행하는 것이 가장 좋습니다. bin
계속하기 전에 폴더 를 만들어야 합니다.
Linux의 경우:
gcc -std=c11 -fPIC -c -I../godot_headers simple.c -o simple.o
gcc -rdynamic -shared simple.o -o ../simple/bin/libsimple.so
clang -std=c11 -fPIC -c -I../godot_headers simple.c -o simple.os
clang -dynamiclib simple.os -o ../simple/bin/libsimple.dylib
Windows의 경우 :
cl /Fosimple.obj /c simple.c /nologo -EHsc -DNDEBUG /MD /I. /I..\godot_headers
link /nologo /dll /out:..\simple\bin\libsimple.dll /implib:..\simple\bin\libsimple.lib simple.obj
GDNativeLibrary (.gdnlib
) 파일 만들기
모듈이 컴파일되었으므로 이제 동적 라이브러리와 함께 배치 할 확장이 있는 해당 GDNativeLibrary 리소스 를 만들어야합니다 .gdnlib
. 이 파일은 Godot가 우리 모듈의 일부이고 플랫폼별로로드해야하는 동적 라이브러리를 알려줍니다.
Godot를 사용하여이 파일을 생성 할 수 있으므로 편집기에서 "간단한"프로젝트를 엽니 다.
Inspector
에서 리소스 생성 버튼을 클릭하고, GDNativeLibrary를 선택. 하단 패널에 상황 별 편집기가 표시되어야합니다.
일반 속성
Inspector에는 라이브러리로드를 제어하는 다양한 속성이 있습니다.
- Load Once
- 우리의 라이브러리는 한 번로드와 같은 데이터를 사용합니다 우리의 라이브러리를 사용하는 각 개별 스크립트입니다. 전역 적으로 정의한 모든 변수는 생성 한 개체의 모든 인스턴스에서 액세스 할 수 있습니다. 한 번로드 가 비활성화 된 경우 스크립트가 라이브러리에 액세스 할 때마다 라이브러리의 새 복사본이 메모리에로드됩니다.
- Singleton
- 우리의 라이브러리는 자동으로로드되고라는 함수가
godot_gdnative_singleton
호출된다. 다른 튜토리얼을 위해 남겨 두겠습니다.
- Symbol Prefix
- 다음과 같은 핵심 기능에 대한 접두어
godot_
에godot_nativescript_init
앞서 본. 정적으로 연결하려는 GDNative 라이브러리를 여러 개 사용하는 경우 다른 접두사를 사용해야합니다. 이것은 다시 별도의 튜토리얼에서 더 자세히 살펴볼 주제입니다.이 플랫폼은 동적 라이브러리를 좋아하지 않기 때문에 현재 iOS에 배포 할 때만 필요합니다.
- Reloadable
- 편집기가 포커스를 잃고 포커스를받을 때 라이브러리를 다시로드 해야하는지 여부를 정의합니다. 일반적으로 외부에서 라이브러리에 대한 변경 사항에서 새 심볼이나 수정 된 심볼을 선택합니다.
플랫폼 라이브러리
GDNativeLibrary 편집기 플러그인을 사용하면 지원하려는 각 플랫폼 및 아키텍처에 대해 두 가지를 구성 할 수 있습니다.
동적 라이브러리 열 (entry
저장된 파일의 섹션) 동적 라이브러리를로드 할 수있는 각 플랫폼 및 기능 조합을 우리에게 알려줍니다. 또한 특정 플랫폼으로 내보낼 때 내 보내야하는 파일을 내보내기에 알립니다.
종속성 열 (또한 dependencies
섹션) 다른 파일 작업에 대한 우리의 라이브러리에 대한 위해 각 플랫폼에 내보낼 수 필요한 고도 (Godot)를 알려줍니다. GDNative 모듈이 타사 라이브러리의 기능을 구현하기 위해 다른 DLL을 사용한다고 가정하면 여기에 해당 DLL을 나열합니다.
이 예에서는 Linux, macOS 및 / 또는 Windows 용 라이브러리 만 빌드 했으므로 폴더 버튼을 클릭하여 관련 필드에 연결할 수 있습니다. 세 라이브러리를 모두 빌드했다면 다음과 같은 것이 있어야합니다.
리소스 저장
그런 다음 bin/libsimple.gdnlib
Inspector의 저장 버튼 을 사용하여 GDNativeLibrary 리소스를 저장할 수 있습니다 .
파일은 텍스트 기반 형식으로 저장되며 다음과 유사한 내용을 가져야합니다.
[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=true
[entry]
OSX.64="res://bin/libsimple.dylib"
OSX.32="res://bin/libsimple.dylib"
Windows.64="res://bin/libsimple.dll"
X11.64="res://bin/libsimple.so"
[dependencies]
OSX.64=[ ]
OSX.32=[ ]
Windows.64=[ ]
X11.64=[ ]
NativeScript (.gdns
) 파일 만들기
.gdnlib
파일을 사용 하여 라이브러리를로드하는 방법을 Godot에 알려 주었으므로, 이제 "Simple"객체 클래스에 대해 알려야합니다. NativeScript 를 위한 .gdns
확장자 리소스를 생성한다.
GDNativeLibrary 리소스와 마찬가지로 버튼을 클릭하여 Inspector에서 새 리소스를 만들고 NativeScript을 선택합니다.
인스펙터는 우리가 채워야 할 몇 가지 속성을 보여줄 것입니다.
- Class Name
- 우리의 C 소스에서 <선언하는 객체 클래스 이름입니다. code>godot_nativescript_register_class</code>에서 지정한 "Simple"을 입력합니다.
- Library
-
.gdnlib
파일을 선택.
마지막 연결
이제 main.gd
코드를 구현할 수 있습니다 .
extends Control
# load the Simple library
onready var data = preload("res://bin/simple.gdns").new()
func _on_Button_pressed():
$Label.text = "Data = " + data.get_data()
추천 방법
I've gotten GDNative to work on iOS and Android but there isn't a single guide to the process anywhere. I mostly grabbed bits and pieces from different places and made my own pipeline.
Here is a brief description:
- Code is just C no C++ since it's easier to compile and I don't have to worry about the STD.
- The build system is based on CMake. Even though SCons is the Godot preferred build system, CMake is simple enough for me to set up and I'm most comfortable with it.
- I'm using the android NDK CMake toolchain file located in
$ANDROID\_SDK\_ROOT/ndk-bundle/build/cmake/android.toolchain.cmake
to compile the android binaries (be sure to download the ndk package from the android skd manager) - I'm using https://github.com/leetal/ios-cmake as a toolchain file to compile the ios library
- The android version has to be compiled as a shared library (.so)
- The iOS version has to be compiled as a static library (.a).
- Finally follow the gdnative configuration in godot as the official guide says https://docs.godotengine.org/en/3.2/tutorials/plugins/gdnative/gdnative-c-example.html#creating-the-gdnativelibrary-gdnlib-file
The proper gdnlib setup was more of a trial and error thing so here you go:
[general]
singleton=false
load_once=true
symbol_prefix="godot_"
reloadable=true
[entry]
Android.armeabi-v7a="res://Minmax/build/android-armeabi-v7a/libminmax.so"
Android.arm64-v8a="res://Minmax/build/android-arm64-v8a/libminmax.so"
Android.x86="res://Minmax/build/android-x86/libminmax.so"
Android.x86_64="res://Minmax/build/android-x86_64/libminmax.so"
OSX.64="res://Minmax/build/Darwin/libminmax.dylib"
Windows.64="res://Minmax/build/Debug/minmax.dll"
X11.64="res://Minmax/build/Linux/libminmax.so"
X11.32="res://Minmax/build/Linux/libminmax.so"
iOS.armv7="res://Minmax/build/ios/libminmax.a"
iOS.arm64="res://Minmax/build/ios/libminmax.a"
[dependencies]
Android.armeabi-v7a=[ ]
Android.arm64-v8a=[ ]
Android.x86=[ ]
Android.x86_64=[ ]
OSX.64=[ ]
Windows.64=[ ]
X11.64=[ ]
X11.32=[ ]
iOS.armv7=[ ]
iOS.arm64=[ ]
Minmax is the name of the folder that contains my GDNative code
Here are a couple of scripts I made that really helped simplify the process: https://gist.github.com/jemsz95/80d4c0de6918989e9b1f503480efa871
There are a lot of assumptions made in those scripts about the project structure and other things. For example the native library is called Minmax, the GDNative headers are in the parent directory. The scripts expect a couple of environment variables.
Edit them to your hearts content and message me if you have any questions.
I'm planning to make a write-up of all of these things with more detail in a bit but I've been busy with work and stuff.
Anyways hope it helps!
댓글
As I understand it, supporting mobile compilation of GDNative C scripts is a little...non-trivial because:
- On Android it likely requires the use of "Java Native Interface"; and,
- On iOS it probably requires use of...something else. :D (Actually, I think it's "doesn't support dynamic libraries".)
Although, having said that, I just did a search for GDNative & Java and found this seemingly complete example of making GDNative C code to run on Android... (so you might be in luck! :) ) :
Also, these links/issues have various background/suggestion/PRs/examples related to the topic:
- Issue: "what about android/ios builds #19"
- PR: "ios and android support #298"
- Issue: "Question: iOS supported? #30"
- https://old.reddit.com/r/godot/comments/aiyqxy/how_to_compile_gdnative_for_android/
Semi-related:
- Scons file for Android engine build: https://github.com/godotengine/godot/blob/master/platform/android/SCsub
- Scons file for iOS engine build: https://github.com/godotengine/godot/blob/master/platform/iphone/SCsub
GDNative 에서 GDScript 함수 호출
Create a Callback Method inside GDScript
You can place this method inside of the same script file where you load() your NativeScript .gdns file as described in previous post.
Pass Class Instance that Contains the Callback from GDScript to Native Code
Your custom native C/C++ function registered with GDNative can take parameters from GDScript which are passed to native code as godot_variant. To be able to call a method on a GDScript object, you can pass an instance of this object as parameter.
extends Node2D
onready var agdn = preload("res://lib/android_gdnative.gdns").new()
...
func _ready():
agdn.test(self)
...
Here I've passed the self variable to my test() function that I've created in the previous post. The method gdscript_callback() shown in the previous step is also defined inside of this same script, therefore I'm passing self variable and not an instance of some other object. How I changed the test()/android_gdnative_test() implementation from previous post is shown in the following step.
Cache the Instance in Native C/C++ code
I've used the GDNative api function godot_variant_new_copy() to create a copy of the self variable passed from GDScript and stored it inside a godot_variant struct(also named self). The self variable was passed from GDScript as the first argument - p_args[0]
...
godot_variant self;
godot_variant android_gdnative_test(godot_object *p_instance, void *p_method_data
, void *p_user_data, int p_num_args, godot_variant **p_args)
{
// Cache object that can be used to call our method in GDScript
api->godot_variant_new_copy(&self, p_args[0]);
...
Call the GDScript Method from C/C++ code
Once you have an instance of the class that contains the callback code, you can use following snippet to call it back
...
// Prepare args to pass from native C++ to GDScript
godot_variant arg;
auto msg = api->godot_string_chars_to_utf8("Message from native C++ code");
api->godot_variant_new_string(&arg, &msg);
std::vector<godot_variant*> args{ &arg };
// Call our method in GDScript
auto cb_name = api->godot_string_chars_to_utf8("gdscript_callback");
godot_variant_call_error err;
api->godot_variant_call(&self, &cb_name, (const godot_variant**)args.data(),
args.size(), &err);
...
You can pass arguments from native C/C++ code to GDScript easily as a variant type. GDNative api provides various functions to convert from different types into a godot_variant. In this case I just passed a string as parameter.
Projects
- GDNative C++ Example
- https://github.com/BastiaanOlij/gdnative_cpp_example
- GDNative C++ example for tutorial
- Using Godot's GDNative on Android
- https://github.com/sixo/gdnative_example
- https://www.sisik.eu/blog/godot/gd-native-on-android
-
Using_Godots_GDNative_on_Android_-_sisik.pdf
- GDNative demos
- https://github.com/godotengine/gdnative-demos
- Demo projects for GDNative
- godot-headers
- https://github.com/godotengine/godot-headers
- Headers for the Godot API supplied by the GDNative module.
See also
Favorite site
- [추천] Reddit - Compiling GDNative for Mobile : godot
- [추천] Youtube - Using C++ with Godot (GDNative Tutorial) "Ten Thousand Subs"
-
GDNative C example — Godot Engine (stable) 문서 (한국어)
Discussion
- Help with building GDNative / C++ for Android - Godot Engine - Q&A
- how to work with gdnative in godot - Godot Engine - Q&A
- what about android/ios builds · Issue #19 · godotengine/gdnative-demos · GitHub
Projects
- gilzoide/high-level-gdnative - Single header GDNative high level API for C/C++