From aa6b33b6260794deef6689bc1bdf2cfae4cf2850 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Mon, 21 Jul 2025 03:05:47 +0200 Subject: [PATCH] [c] bindgen based bindings for Rust --- spine-c/tests/rust-wasm/Cargo.lock | 271 +++++++++++++++++++++++++++++ spine-c/tests/rust-wasm/Cargo.toml | 3 +- spine-c/tests/rust-wasm/build.rs | 16 ++ spine-c/tests/rust-wasm/src/lib.rs | 47 +---- 4 files changed, 293 insertions(+), 44 deletions(-) diff --git a/spine-c/tests/rust-wasm/Cargo.lock b/spine-c/tests/rust-wasm/Cargo.lock index f514b7305..6c4f1e288 100644 --- a/spine-c/tests/rust-wasm/Cargo.lock +++ b/spine-c/tests/rust-wasm/Cargo.lock @@ -2,6 +2,41 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + [[package]] name = "cc" version = "1.2.30" @@ -11,6 +46,160 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "prettyplease" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "shlex" version = "1.3.0" @@ -21,5 +210,87 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" name = "spine-c-wasm-test" version = "0.1.0" dependencies = [ + "bindgen", "cc", ] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" diff --git a/spine-c/tests/rust-wasm/Cargo.toml b/spine-c/tests/rust-wasm/Cargo.toml index 0d2e03ba5..ecb4bfeaa 100644 --- a/spine-c/tests/rust-wasm/Cargo.toml +++ b/spine-c/tests/rust-wasm/Cargo.toml @@ -9,4 +9,5 @@ crate-type = ["cdylib"] [dependencies] [build-dependencies] -cc = "1.0" \ No newline at end of file +cc = "1.0" +bindgen = "0.70" \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/build.rs b/spine-c/tests/rust-wasm/build.rs index b79f2aca1..af154cc36 100644 --- a/spine-c/tests/rust-wasm/build.rs +++ b/spine-c/tests/rust-wasm/build.rs @@ -76,9 +76,25 @@ fn main() { cpp_build.compile("spine"); + // Generate bindings with bindgen + let bindings = bindgen::Builder::default() + .header("../../include/spine-c.h") + .clang_arg("-I../../include") + .clang_arg("-I../../../spine-cpp/include") + .clang_arg("-I../../src") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Unable to generate bindings"); + + let out_path = std::path::PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); + // Link libraries - no C++ stdlib since we're using no-cpprt variant // The no-cpprt.cpp provides minimal runtime stubs println!("cargo:rerun-if-changed=../../spine-cpp/src"); println!("cargo:rerun-if-changed=../../src"); + println!("cargo:rerun-if-changed=../../include/spine-c.h"); } \ No newline at end of file diff --git a/spine-c/tests/rust-wasm/src/lib.rs b/spine-c/tests/rust-wasm/src/lib.rs index 89fc291bd..03a9a2e64 100644 --- a/spine-c/tests/rust-wasm/src/lib.rs +++ b/spine-c/tests/rust-wasm/src/lib.rs @@ -1,38 +1,8 @@ use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_float, c_int, c_void}; -// Opaque pointer types matching spine-c - all are SPINE_OPAQUE_TYPE which means pointers -type SpineAtlas = *mut c_void; -type SpineSkeletonData = *mut c_void; -type SpineSkeleton = *mut c_void; -type SpineSkeletonDataResult = *mut c_void; // This is also an opaque pointer! - -// FFI bindings to spine-c API (minimal subset for testing) -extern "C" { - fn spine_bone_set_y_down(yDown: bool); - fn spine_atlas_load_callback( - data: *const c_char, - atlasPath: *const c_char, - textureLoader: extern "C" fn(*const c_char) -> *mut c_void, - textureUnloader: extern "C" fn(*mut c_void) -> (), - ) -> SpineAtlas; - fn spine_atlas_dispose(atlas: SpineAtlas); - fn spine_skeleton_data_load_binary( - atlas: SpineAtlas, - data: *const u8, - length: i32, - skeletonPath: *const c_char, - ) -> SpineSkeletonDataResult; - fn spine_skeleton_data_result_get_data(result: SpineSkeletonDataResult) -> SpineSkeletonData; - fn spine_skeleton_data_result_get_error(result: SpineSkeletonDataResult) -> *const c_char; - fn spine_skeleton_data_result_dispose(result: SpineSkeletonDataResult); - fn spine_skeleton_create(skeletonData: SpineSkeletonData) -> SpineSkeleton; - fn spine_skeleton_dispose(skeleton: SpineSkeleton); - fn spine_skeleton_setup_pose(skeleton: SpineSkeleton); - fn spine_skeleton_update_world_transform_1(skeleton: SpineSkeleton, physics: c_int); - fn spine_skeleton_get_x(skeleton: SpineSkeleton) -> c_float; - fn spine_skeleton_get_y(skeleton: SpineSkeleton) -> c_float; -} +// Include the generated bindings +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); // Headless texture loader functions with debug prints extern "C" fn headless_texture_loader(path: *const c_char) -> *mut c_void { @@ -82,8 +52,8 @@ pub extern "C" fn test_spine_basic() -> c_int { let atlas = spine_atlas_load_callback( atlas_data.as_ptr(), atlas_dir.as_ptr(), - headless_texture_loader, - headless_texture_unloader, + Some(headless_texture_loader), + Some(headless_texture_unloader), ); println!("Atlas loaded: {:?}", atlas); @@ -203,22 +173,13 @@ mod wasm { } } -// mod bindgen_test; // Temporarily disabled - #[cfg(test)] mod tests { use super::*; - // use crate::bindgen_test::*; #[test] fn test_spine_basic_works() { let result = test_spine_basic(); assert_eq!(result, 0, "Spine basic test should succeed"); } - - // #[test] - // fn test_bindgen_version() { - // let result = test_bindgen_spine(); - // assert_eq!(result, 0, "Bindgen test should succeed"); - // } } \ No newline at end of file