mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 21:07:43 +00:00
feat: impl C ffi
This commit is contained in:
parent
a26d4b0122
commit
95309db710
5 changed files with 70 additions and 33 deletions
2
crates/loro-ffi/.gitignore
vendored
Normal file
2
crates/loro-ffi/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
examples/cpp/loro
|
||||
examples/cpp/*.a
|
|
@ -1,35 +1,8 @@
|
|||
extern crate cbindgen;
|
||||
|
||||
use cbindgen::Config;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
|
||||
let package_name = env::var("CARGO_PKG_NAME").unwrap();
|
||||
let output_file = target_dir()
|
||||
.join(format!("{}.hpp", package_name))
|
||||
.display()
|
||||
.to_string();
|
||||
|
||||
let config = Config {
|
||||
namespace: Some(String::from("loro_ffi")),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let config = cbindgen::Config::from_file("cbindgen.toml")
|
||||
.expect("Unable to find cbindgen.toml configuration file");
|
||||
cbindgen::generate_with_config(&crate_dir, config)
|
||||
.unwrap()
|
||||
.write_to_file(&output_file);
|
||||
}
|
||||
|
||||
/// Find the location of the `target/` directory. Note that this may be
|
||||
/// overridden by `cmake`, so we also need to check the `CARGO_TARGET_DIR`
|
||||
/// variable.
|
||||
fn target_dir() -> PathBuf {
|
||||
if let Ok(target) = env::var("CARGO_TARGET_DIR") {
|
||||
PathBuf::from(target)
|
||||
} else {
|
||||
PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("target")
|
||||
}
|
||||
.write_to_file("target/loro_ffi.h");
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
include_guard = "libloro_ffi_h"
|
||||
header = """
|
||||
typedef struct LoroCore {} LoroCore;
|
||||
|
||||
typedef struct Text {} Text;
|
||||
"""
|
||||
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
||||
language = "C"
|
||||
|
|
14
crates/loro-ffi/examples/cpp/loro.cpp
Normal file
14
crates/loro-ffi/examples/cpp/loro.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <stdio.h>
|
||||
extern "C" {
|
||||
#include "../../target/loro_ffi.h"
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
LoroCore* loro = loro_new();
|
||||
Text* text = loro_get_text(loro, "text");
|
||||
text_insert(text, loro, 0, "abc");
|
||||
char* str = text_value(text);
|
||||
printf("%s", str);
|
||||
text_free(text);
|
||||
loro_free(loro);
|
||||
}
|
|
@ -1,4 +1,9 @@
|
|||
use loro_core::LoroCore;
|
||||
use std::ffi::{c_char, c_uint, CStr, CString};
|
||||
|
||||
pub type LoroCore = loro_core::LoroCore;
|
||||
pub type Text = loro_core::Text;
|
||||
pub type List = loro_core::List;
|
||||
pub type Map = loro_core::Map;
|
||||
|
||||
/// create Loro with a random unique client id
|
||||
#[no_mangle]
|
||||
|
@ -13,3 +18,42 @@ pub unsafe extern "C" fn loro_free(loro: *mut LoroCore) {
|
|||
drop(Box::from_raw(loro));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn loro_get_text(loro: *mut LoroCore, id: *const c_char) -> *mut Text {
|
||||
assert!(!loro.is_null());
|
||||
assert!(!id.is_null());
|
||||
let id = CStr::from_ptr(id).to_str().unwrap();
|
||||
let text = loro.as_mut().unwrap().get_text(id);
|
||||
Box::into_raw(Box::new(text))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn text_free(text: *mut Text) {
|
||||
if !text.is_null() {
|
||||
drop(Box::from_raw(text));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn text_insert(
|
||||
text: *mut Text,
|
||||
ctx: *const LoroCore,
|
||||
pos: *const c_uint,
|
||||
value: *const c_char,
|
||||
) {
|
||||
assert!(!text.is_null());
|
||||
assert!(!ctx.is_null());
|
||||
let text = text.as_mut().unwrap();
|
||||
let ctx = ctx.as_ref().unwrap();
|
||||
let value = CStr::from_ptr(value).to_str().unwrap();
|
||||
text.insert(ctx, pos as usize, value).unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn text_value(text: *mut Text) -> *mut c_char {
|
||||
assert!(!text.is_null());
|
||||
let text = text.as_mut().unwrap();
|
||||
let value = text.get_value().as_string().unwrap().to_string();
|
||||
CString::new(value).unwrap().into_raw()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue