Skip to content

Add C bindings #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 33 commits into
base: default
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ecbc917
[wip] Add C bindings
goto-bus-stop Aug 10, 2019
28adb35
Merge branch 'default' into c
goto-bus-stop Sep 14, 2019
787e3b0
c: expose more scx conversion methods
goto-bus-stop Sep 14, 2019
2cb1d00
ci: try publishing dll artifacts
goto-bus-stop Sep 14, 2019
f9ca87a
ci: --release build for c libs
goto-bus-stop Sep 14, 2019
47e2396
build all cgenie crates
goto-bus-stop Sep 14, 2019
d4302f1
ci: script → bash
goto-bus-stop Sep 14, 2019
a4ad32e
ci: ?
goto-bus-stop Sep 14, 2019
3415e7d
c: build static libs
goto-bus-stop Sep 15, 2019
b11ee69
c: check `scenario` validity before saving
goto-bus-stop Sep 15, 2019
e299fb5
Merge branch 'default' into c
goto-bus-stop Dec 5, 2019
270b75f
c: save scenarios to specified version
goto-bus-stop Dec 5, 2019
79451fd
scx: add 0/1 DLC Packages
goto-bus-stop Dec 5, 2019
ae0fc1e
scx: support triggers without unit/object id in conversion
goto-bus-stop Dec 7, 2019
b1a07a3
ci: upload static libraries too
goto-bus-stop Dec 7, 2019
f32ea8d
build 32 bit libraries
goto-bus-stop Dec 7, 2019
64aabeb
ci: only prepare C libraries on windows
goto-bus-stop Dec 7, 2019
e18f6ed
build: fix output dir
goto-bus-stop Dec 7, 2019
fa32593
try this?
goto-bus-stop Dec 7, 2019
7c64086
ci: fix toolchain name
goto-bus-stop Dec 7, 2019
7f64286
ci: fix toolchain name
goto-bus-stop Dec 7, 2019
079d890
ci: swap
goto-bus-stop Dec 7, 2019
bcc3e93
Merge branch 'default' into c
goto-bus-stop Mar 10, 2020
ced7148
ci: add artifact generation on Github Actions
goto-bus-stop Mar 10, 2020
ea598a4
ci: try this matrix syntax
goto-bus-stop Mar 10, 2020
d735ddb
ci: add 32 bit
goto-bus-stop Mar 10, 2020
6a8ff35
ci: fix name
goto-bus-stop Mar 10, 2020
b847ef2
ci: fix path
goto-bus-stop Mar 10, 2020
6bf4d2d
c: add c examples
goto-bus-stop Mar 21, 2020
d321f89
Merge branch 'default' into c
goto-bus-stop Mar 21, 2020
c32e886
Merge branch 'default' into c
goto-bus-stop Apr 16, 2020
9ddaffc
c: do clippy a lol
goto-bus-stop Apr 16, 2020
f1642c7
Merge branch 'default' into c
goto-bus-stop May 27, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/artifact.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
on: [push]

name: Artifacts

jobs:
x64:
name: Build 64 bit C Libraries
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Build cgenie libraries
uses: actions-rs/cargo@v1
with:
command: build
args: --release -p cgenie-drs -p cgenie-hki -p cgenie-lang -p cgenie-scx -p cgenie
- name: Prepare artifact
run: |
mkdir -p artifact/libs/
cp target/release/*.dll artifact/libs/
cp target/release/*.lib artifact/libs/
cp -R c/include artifact/
- uses: actions/upload-artifact@v1
with:
name: cgenie-x64-win
path: artifact
x86:
name: Build 32 bit C Libraries
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: i686-pc-windows-msvc
override: true
- name: Build cgenie libraries
uses: actions-rs/cargo@v1
with:
command: build
args: --target i686-pc-windows-msvc --release -p cgenie-drs -p cgenie-hki -p cgenie-lang -p cgenie-scx -p cgenie
- name: Prepare artifact
run: |
mkdir -p artifact/libs/
cp target/i686-pc-windows-msvc/release/*.dll artifact/libs/
cp target/i686-pc-windows-msvc/release/*.lib artifact/libs/
cp -R c/include artifact/
- uses: actions/upload-artifact@v1
with:
name: cgenie-x86-win
path: artifact
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,13 @@ members = [
"crates/genie-rec",
"crates/genie-scx",
"crates/genie-support",
"crates/jascpal"
"crates/jascpal",

"c/cgenie",
# need to figure out FFI generics to make this work
# "c/cgenie-cpx",
"c/cgenie-drs",
"c/cgenie-hki",
"c/cgenie-lang",
"c/cgenie-scx",
]
16 changes: 16 additions & 0 deletions c/cgenie-cpx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgenie-cpx"
version = "0.1.0"
authors = ["Renée Kooi <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
description = "C-compatible APIs for the genie-cpx library"
homepage = "https://github.com/SiegeEngineers/genie-rs"
repository = "https://github.com/SiegeEngineers/genie-rs"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
ffi-support = "^0.3.5"
genie-cpx = { path = "../../crates/genie-cpx" }
31 changes: 31 additions & 0 deletions c/cgenie-cpx/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use ffi_support::FfiStr;
use genie_cpx::Campaign;
use std::{fs::File, io::{Read, Seek, Cursor}, ptr};

/// Open and read a campaign file.
#[no_mangle]
pub extern "C" fn cgcpx_load(path: FfiStr) -> *mut Campaign {
if let Some(path) = path.as_opt_str() {
if let Ok(mut file) = File::open(path) {
Campaign::from(&mut file)
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}

/// Read a campaign file from a byte array.
#[no_mangle]
pub extern "C" fn cgcpx_load_mem(input: *const u8, size: usize) -> *mut Campaign {
let slice = unsafe { std::slice::from_raw_parts(input, size) };
let mut cursor = Cursor::new(slice);
Campaign::from(&mut cursor)
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
}
16 changes: 16 additions & 0 deletions c/cgenie-drs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgenie-drs"
version = "0.1.0"
authors = ["Renée Kooi <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
description = "C-compatible APIs for the genie-drs library"
homepage = "https://github.com/SiegeEngineers/genie-rs"
repository = "https://github.com/SiegeEngineers/genie-rs"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
ffi-support = "^0.3.5"
genie-drs = { path = "../../crates/genie-drs" }
31 changes: 31 additions & 0 deletions c/cgenie-drs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use ffi_support::FfiStr;
use genie_drs::{DRSReader, DRSWriter};
use std::{fs::File, ptr};

type DRSR = (File, DRSReader);

/// Open a drs archive.
#[no_mangle]
pub extern "C" fn cgdrs_load(path: FfiStr) -> *mut DRSR {
if let Some(path) = path.as_opt_str() {
if let Ok(mut file) = File::open(path) {
DRSReader::new(&mut file)
.map(move |drs| (file, drs))
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}

/// Close a drs archive.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cgdrs_free(drs: *mut DRSR) {
let pair = unsafe { Box::from_raw(drs) };
drop(pair);
}
16 changes: 16 additions & 0 deletions c/cgenie-hki/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgenie-hki"
version = "0.1.0"
authors = ["Renée Kooi <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
description = "C-compatible APIs for the genie-hki library"
homepage = "https://github.com/SiegeEngineers/genie-rs"
repository = "https://github.com/SiegeEngineers/genie-rs"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
ffi-support = "^0.3.5"
genie-hki = { path = "../../crates/genie-hki" }
51 changes: 51 additions & 0 deletions c/cgenie-hki/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use ffi_support::FfiStr;
use genie_hki::HotkeyInfo;
use std::{fs::File, io::Cursor, ptr};

/// Open and read a hotkey file.
#[no_mangle]
pub extern "C" fn cghki_load(path: FfiStr) -> *mut HotkeyInfo {
if let Some(path) = path.as_opt_str() {
if let Ok(mut file) = File::open(path) {
HotkeyInfo::from(&mut file)
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}

/// Read a hotkey file from a byte array.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cghki_load_mem(input: *const u8, size: usize) -> *mut HotkeyInfo {
let slice = unsafe { std::slice::from_raw_parts(input, size) };
let mut cursor = Cursor::new(slice);
HotkeyInfo::from(&mut cursor)
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
}

/// Save the hotkeys to a file.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cghki_save(hki: *mut HotkeyInfo, path: FfiStr) -> u32 {
if let Some(path) = path.as_opt_str() {
if let Ok(mut file) = File::create(path) {
if unsafe { &*hki }.write_to(&mut file).is_ok() {
0
} else {
3
}
} else {
2
}
} else {
1
}
}
16 changes: 16 additions & 0 deletions c/cgenie-lang/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgenie-lang"
version = "0.1.0"
authors = ["Renée Kooi <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
description = "C-compatible API for the genie-lang library"
homepage = "https://github.com/SiegeEngineers/genie-rs"
repository = "https://github.com/SiegeEngineers/genie-rs"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
ffi-support = "^0.3.5"
genie-lang = { path = "../../crates/genie-lang" }
113 changes: 113 additions & 0 deletions c/cgenie-lang/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use ffi_support::FfiStr;
use genie_lang::{LangFile, LangFileType, StringKey};
use std::{fs::File, ptr};

fn try_read_file(t: LangFileType, path: FfiStr) -> *mut LangFile {
if let Some(path) = path.as_opt_str() {
if let Ok(file) = File::open(path) {
t.read_from(file)
.map(Box::new)
.map(Box::into_raw)
.unwrap_or(ptr::null_mut())
} else {
ptr::null_mut()
}
} else {
ptr::null_mut()
}
}

fn try_create_file(path: FfiStr) -> Option<File> {
path.as_opt_str().and_then(|path| File::create(path).ok())
}

/// Load a .ini language file.
#[no_mangle]
pub extern "C" fn cglang_load_ini(path: FfiStr) -> *mut LangFile {
try_read_file(LangFileType::Ini, path)
}

/// Load an HD Edition key-value.txt language file.
#[no_mangle]
pub extern "C" fn cglang_load_keyval(path: FfiStr) -> *mut LangFile {
try_read_file(LangFileType::KeyValue, path)
}

/// Load a classic DLL language file.
#[no_mangle]
pub extern "C" fn cglang_load_dll(path: FfiStr) -> *mut LangFile {
try_read_file(LangFileType::Dll, path)
}

/// Get an integer-indexed string.
///
/// The returned string is owned by the `cgenie_lang` pointer.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cglang_get(file: *const LangFile, index: u32) -> *const u8 {
if file.is_null() {
ptr::null()
} else {
unsafe { &*file }
.get(&StringKey::from(index))
.map(|s| s.as_ptr())
.unwrap_or(ptr::null())
}
}

/// Get a name-indexed string.
///
/// The returned string is owned by the `cgenie_lang` pointer.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cglang_get_named(file: *const LangFile, index: FfiStr) -> *const u8 {
match (file.is_null(), index.as_opt_str()) {
(true, Some(index)) => {
unsafe { &*file }
.get(&StringKey::from(index))
.map(|s| s.as_ptr())
.unwrap_or(ptr::null())
}
_ => ptr::null(),
}
}

/// Save a .ini language file.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cglang_save_ini(file: *mut LangFile, path: FfiStr) -> u32 {
let mut output = match try_create_file(path) {
Some(output) => output,
_ => return 1,
};
if unsafe { &*file }.write_to_ini(&mut output).is_ok() {
0
} else {
2
}
}

/// Save an HD Edition key-value.txt language file.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cglang_save_keyval(file: *mut LangFile, path: FfiStr) -> u32 {
let mut output = match try_create_file(path) {
Some(output) => output,
_ => return 1,
};
if unsafe { &*file }.write_to_keyval(&mut output).is_ok() {
0
} else {
2
}
}

/// Free all language file resources.
#[no_mangle]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn cglang_free(file: *mut LangFile) {
if !file.is_null() {
let file = unsafe { Box::from_raw(file) };
drop(file);
}
}
16 changes: 16 additions & 0 deletions c/cgenie-scx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgenie-scx"
version = "0.1.0"
authors = ["Renée Kooi <[email protected]>"]
edition = "2018"
license = "GPL-3.0"
description = "C-compatible APIs for the genie-scx library"
homepage = "https://github.com/SiegeEngineers/genie-rs"
repository = "https://github.com/SiegeEngineers/genie-rs"

[lib]
crate-type = ["cdylib", "staticlib", "rlib"]

[dependencies]
ffi-support = "^0.3.5"
genie-scx = { path = "../../crates/genie-scx" }
Loading