Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NxScript Native Bindings

Build and use NxScript from any engine or language via native shared libraries.

Build everything

cd bindings
python3 build.py          # all targets, debug
python3 build.py --release # optimized
python3 build.py c         # only C binding
python3 build.py gdext     # only GDExtension

Requires: haxe 4.3+, haxelib install hxcpp


C / C++ (bindings/c/)

Builds a shared library exposable to any C/C++ engine.

haxe bindings/c/c_binding.hxml
# Output: bindings/c/out/
#   Windows → NxScript.dll
#   Linux   → libNxScript.so
#   Mac     → libNxScript.dylib
#include "nxscript.h"

int vm = nxs_create();
nxs_run(vm, "func greet(name) { return 'hi ' + name }", "test.nx");

int arg = nxs_value_string("world");
int res = nxs_call1(vm, "greet", arg);
printf("%s\n", nxs_value_get_string(res)); // hi world

nxs_value_free(arg);
nxs_value_free(res);
nxs_free(vm);

Full API

// VM lifecycle
int  nxs_create();
void nxs_free(int vm);
void nxs_reset(int vm);          // preserves statics + classes

// Execution
int  nxs_run(int vm, const char* source, const char* name);
int  nxs_run_file(int vm, const char* path);
int  nxs_run_dir(int vm, const char* dir, int recursive);

// Calling script functions (0–4 args)
int nxs_call0(int vm, const char* fn);
int nxs_call1(int vm, const char* fn, int a0);
int nxs_call2(int vm, const char* fn, int a0, int a1);
int nxs_call3(int vm, const char* fn, int a0, int a1, int a2);
int nxs_call4(int vm, const char* fn, int a0, int a1, int a2, int a3);

// Globals
void   nxs_set_number(int vm, const char* name, double value);
void   nxs_set_string(int vm, const char* name, const char* value);
void   nxs_set_bool  (int vm, const char* name, int value);
double nxs_get_number(int vm, const char* name);
const char* nxs_get_string(int vm, const char* name);
int    nxs_get_bool  (int vm, const char* name);

// Value handles (for call args/results)
int  nxs_value_number(double n);
int  nxs_value_string(const char* s);
int  nxs_value_bool(int b);
void nxs_value_free(int val);
double      nxs_value_get_number(int val);
const char* nxs_value_get_string(int val);
const char* nxs_value_type(int val);       // "number","string","bool","null",...

// Native callbacks
typedef const char* (*NxsCallback)(const char* args);
void nxs_register_string_callback(int vm, const char* name, int arity, NxsCallback cb);

// Preprocessor
void nxs_define(int vm, const char* name, int value);

// Sandbox
void nxs_enable_sandbox(int vm);

// Errors
const char* nxs_get_error(int vm);
void nxs_clear_error(int vm);

Godot 4 (bindings/gdextension/)

Recommended approach: Use the C binding from a GDExtension C++ project.

  1. Build bindings/c/ first
  2. Copy nxscript.h + libNxScript.* to your GDExtension project
  3. Use NxScriptGDExt.cpp as your GDExtension class template
// In your GDExtension node:
#include "nxscript.h"

void _ready() {
    vm = nxs_create();
    nxs_run_file(vm, "res://scripts/enemy.nx");
}

void _process(double delta) {
    nxs_set_number(vm, "delta", delta);
    nxs_call0(vm, "update");
}

GDScript after registration:

var nx = NxVM.new()
nx.run_file("res://scripts/enemy.nx")
nx.define("debug", true)

func _process(delta):
    nx.set_number("delta", delta)
    nx.call("update")

var hp = nx.get_number("hp")

Unity (bindings/unity/)

Uses P/Invoke on the C DLL. Copy NxScriptUnity.cs to Assets/Scripts/ and the DLL to Assets/Plugins/.

using NxScript;

NxVM vm = new NxVM();
vm.RunScript(@"
    static var score = 0
    func addScore(n) { score = score + n }
    func getScore()  { return score }
", "game.nx");

void Update() {
    vm.SetFloat("delta", Time.deltaTime);
    vm.Call("update");
}

// Or use the MonoBehaviour component:
// Add NxScriptComponent to any GameObject
// Set scriptFile = "game.nx" in Inspector

Custom engine / any language

If your language can call C functions via FFI, use the C API directly.

Examples:

  • Python: ctypes.CDLL("libNxScript.so")
  • Rust: bindgen on nxscript.h
  • Lua: ffi.load("NxScript")
  • GML (GameMaker): external_define + external_call

Script example that works from any binding

# enemy.nx

static var total_enemies = 0

class Enemy {
    var hp = 100
    var x  = 0
    var y  = 0

    func new(px, py)
    {
        this.x = px
        this.y = py
        Enemy.total_enemies++
    }

    func take_damage(amount)
    {
        this.hp -= amount
        return this.hp > 0
    }

    func is_dead() { return this.hp <= 0 }
}

func create_enemy(x, y) {
    return new Enemy(x, y)
}

func get_enemy_count() {
    return Enemy.total_enemies
}
// host (C)
int vm = nxs_create();
nxs_run_file(vm, "enemy.nx");

int xe = nxs_value_number(100);
int ye = nxs_value_number(200);
nxs_call2(vm, "create_enemy", xe, ye);   // spawns Enemy
nxs_value_free(xe); nxs_value_free(ye);

int count = nxs_call0(vm, "get_enemy_count");
printf("Enemies: %d\n", (int)nxs_value_get_number(count));
nxs_value_free(count);

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages