This repository has been archived by the owner on Nov 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Parity as a library #8412
Merged
Merged
Parity as a library #8412
Changes from 6 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3397b18
Parity as a library
tomaka e63313d
Fix concerns
tomaka 799edbf
Allow using a null on_client_restart_cb
tomaka c79f7fd
Fix more concerns
tomaka b63118e
Merge remote-tracking branch 'upstream/master' into parity-as-a-lib
tomaka 7257cfd
Merge remote-tracking branch 'upstream/master' into parity-as-a-lib
tomaka a7ca08c
Test the C library in test.sh
tomaka eb02ac4
Reduce CMake version to 3.5
tomaka df5236d
Move the clib test before cargo test
tomaka 485088d
Add println in test
tomaka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
description = "C bindings for the Parity Ethereum client" | ||
name = "parity-clib" | ||
version = "1.11.0" | ||
license = "GPL-3.0" | ||
authors = ["Parity Technologies <[email protected]>"] | ||
|
||
[lib] | ||
name = "parity" | ||
crate-type = ["cdylib", "staticlib"] | ||
|
||
[dependencies] | ||
parity = { path = "../", default-features = false } | ||
|
||
[features] | ||
default = [] | ||
final = ["parity/final"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright 2018 Parity Technologies (UK) Ltd. | ||
// This file is part of Parity. | ||
|
||
// Parity is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// Parity is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with Parity. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
#ifndef _PARITY_H_INCLUDED_ | ||
#define _PARITY_H_INCLUDED_ | ||
|
||
#include <stddef.h> | ||
|
||
/// Parameters to pass to `parity_start`. | ||
struct ParityParams { | ||
/// Configuration object, as handled by the `parity_config_*` functions. | ||
/// Note that calling `parity_start` will destroy the configuration object (even on failure). | ||
void *configuration; | ||
|
||
/// Callback function to call when the client receives an RPC request to change its chain spec. | ||
/// | ||
/// Will only be called if you enable the `--can-restart` flag. | ||
/// | ||
/// The first parameter of the callback is the value of `on_client_restart_cb_custom`. | ||
/// The second and third parameters of the callback are the string pointer and length. | ||
void (*on_client_restart_cb)(void* custom, const char* new_chain, size_t new_chain_len); | ||
|
||
/// Custom parameter passed to the `on_client_restart_cb` callback as first parameter. | ||
void *on_client_restart_cb_custom; | ||
}; | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/// Builds a new configuration object by parsing a list of CLI arguments. | ||
/// | ||
/// The first two parameters are string pointers and string lengths. They must have a length equal | ||
/// to `len`. The strings don't need to be zero-terminated. | ||
/// | ||
/// On success, the produced object will be written to the `void*` pointed by `out`. | ||
/// | ||
/// Returns 0 on success, and non-zero on error. | ||
/// | ||
/// # Example | ||
/// | ||
/// ```no_run | ||
/// void* cfg; | ||
/// const char *args[] = {"--light", "--can-restart"}; | ||
/// size_t str_lens[] = {7, 13}; | ||
/// if (parity_config_from_cli(args, str_lens, 2, &cfg) != 0) { | ||
/// return 1; | ||
/// } | ||
/// ``` | ||
/// | ||
int parity_config_from_cli(char const* const* args, size_t const* arg_lens, size_t len, void** out); | ||
|
||
/// Destroys a configuration object created earlier. | ||
/// | ||
/// **Important**: You probably don't need to call this function. Calling `parity_start` destroys | ||
/// the configuration object as well (even on failure). | ||
void parity_config_destroy(void* cfg); | ||
|
||
/// Starts the parity client in background threads. Returns a pointer to a struct that represents | ||
/// the running client. Can also return NULL if the execution completes instantly. | ||
/// | ||
/// **Important**: The configuration object passed inside `cfg` is destroyed when you | ||
/// call `parity_start` (even on failure). | ||
/// | ||
/// On success, the produced object will be written to the `void*` pointed by `out`. | ||
/// | ||
/// Returns 0 on success, and non-zero on error. | ||
int parity_start(const ParityParams* params, void** out); | ||
|
||
/// Destroys the parity client created with `parity_start`. | ||
/// | ||
/// **Warning**: `parity_start` can return NULL if execution finished instantly, in which case you | ||
/// must not call this function. | ||
void parity_destroy(void* parity); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // include guard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// Copyright 2018 Parity Technologies (UK) Ltd. | ||
// This file is part of Parity. | ||
|
||
// Parity is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// Parity is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with Parity. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
//! Note that all the structs and functions here are documented in `parity.h`, to avoid | ||
//! duplicating documentation. | ||
|
||
extern crate parity; | ||
|
||
use std::os::raw::{c_char, c_void, c_int}; | ||
use std::panic; | ||
use std::ptr; | ||
use std::slice; | ||
|
||
#[repr(C)] | ||
pub struct ParityParams { | ||
pub configuration: *mut c_void, | ||
pub on_client_restart_cb: Option<extern "C" fn(*mut c_void, *const c_char, usize)>, | ||
pub on_client_restart_cb_custom: *mut c_void, | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn parity_config_from_cli(args: *const *const c_char, args_lens: *const usize, len: usize, output: *mut *mut c_void) -> c_int { | ||
unsafe { | ||
panic::catch_unwind(|| { | ||
*output = ptr::null_mut(); | ||
|
||
let args = { | ||
let arg_ptrs = slice::from_raw_parts(args, len); | ||
let arg_lens = slice::from_raw_parts(args_lens, len); | ||
|
||
let mut args = Vec::with_capacity(len + 1); | ||
args.push("parity".to_owned()); | ||
|
||
for (&arg, &len) in arg_ptrs.iter().zip(arg_lens.iter()) { | ||
let string = slice::from_raw_parts(arg as *const u8, len); | ||
match String::from_utf8(string.to_owned()) { | ||
Ok(a) => args.push(a), | ||
Err(_) => return 1, | ||
}; | ||
} | ||
|
||
args | ||
}; | ||
|
||
match parity::Configuration::parse_cli(&args) { | ||
Ok(mut cfg) => { | ||
// Always disable the auto-updater when used as a library. | ||
cfg.args.arg_auto_update = "none".to_owned(); | ||
|
||
let cfg = Box::into_raw(Box::new(cfg)); | ||
*output = cfg as *mut _; | ||
0 | ||
}, | ||
Err(_) => { | ||
1 | ||
}, | ||
} | ||
}).unwrap_or(1) | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn parity_config_destroy(cfg: *mut c_void) { | ||
unsafe { | ||
let _ = panic::catch_unwind(|| { | ||
let _cfg = Box::from_raw(cfg as *mut parity::Configuration); | ||
}); | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn parity_start(cfg: *const ParityParams, output: *mut *mut c_void) -> c_int { | ||
unsafe { | ||
panic::catch_unwind(|| { | ||
*output = ptr::null_mut(); | ||
let cfg: &ParityParams = &*cfg; | ||
|
||
let config = Box::from_raw(cfg.configuration as *mut parity::Configuration); | ||
|
||
let on_client_restart_cb = { | ||
struct Cb(Option<extern "C" fn(*mut c_void, *const c_char, usize)>, *mut c_void); | ||
unsafe impl Send for Cb {} | ||
unsafe impl Sync for Cb {} | ||
impl Cb { | ||
fn call(&self, new_chain: String) { | ||
if let Some(ref cb) = self.0 { | ||
cb(self.1, new_chain.as_bytes().as_ptr() as *const _, new_chain.len()) | ||
} | ||
} | ||
} | ||
let cb = Cb(cfg.on_client_restart_cb, cfg.on_client_restart_cb_custom); | ||
move |new_chain: String| { cb.call(new_chain); } | ||
}; | ||
|
||
let action = match parity::start(*config, on_client_restart_cb, || {}) { | ||
Ok(action) => action, | ||
Err(_) => return 1, | ||
}; | ||
|
||
match action { | ||
parity::ExecutionAction::Instant(Some(s)) => { println!("{}", s); 0 }, | ||
parity::ExecutionAction::Instant(None) => 0, | ||
parity::ExecutionAction::Running(client) => { | ||
*output = Box::into_raw(Box::<parity::RunningClient>::new(client)) as *mut c_void; | ||
0 | ||
} | ||
} | ||
}).unwrap_or(1) | ||
} | ||
} | ||
|
||
#[no_mangle] | ||
pub extern fn parity_destroy(client: *mut c_void) { | ||
unsafe { | ||
let _ = panic::catch_unwind(|| { | ||
let client = Box::from_raw(client as *mut parity::RunningClient); | ||
client.shutdown(); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't
pub unsafe extern "C" fn ...
signature recommended for c api?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the official docs, no: https://doc.rust-lang.org/nomicon/ffi.html#calling-rust-code-from-c
I agree that this is really debatable, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, i remember i was given this recommendation by Rust guys though
nvm