1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
extern crate libloading as libl;
use std::collections::HashMap;
use std::ffi::CString;
use std::io;
use std::os::raw::{c_char, c_int, c_uint, c_void};
fn to_c_str<T: Into<Vec<u8>>>(t: T) -> *const c_char {
CString::new(t).unwrap().as_ptr() as *const c_char
}
type CoreClrInitializeFn = unsafe extern fn(
*const c_char,
*const c_char,
c_int,
*const *const c_char,
*const *const c_char,
*const *const c_void,
*const c_uint) -> c_int;
type CoreClrShutdownFn = unsafe extern fn(*const c_void, c_uint) -> c_int;
type CoreClrShutdown2Fn = unsafe extern fn(*const c_void, c_uint, *const c_int) -> c_int;
type CoreClrCreateDelegateFn = unsafe extern fn(
*const c_void,
c_uint,
*const c_char,
*const c_char,
*const c_char,
*const *const c_void) -> c_int;
pub struct UnixCoreClr {
host_handle: *const c_void,
domain_id: c_uint
}
impl UnixCoreClr {
fn library() -> libl::Result<libl::Library> {
libl::Library::new("/usr/local/share/dotnet/shared/Microsoft.NETCore.App/2.0.0/libcoreclr.dylib")
}
pub fn init(
exe_path: &str,
app_domain_friendly_name: &str,
properties_option: Option<HashMap<&str, &str>>) -> libl::Result<UnixCoreClr>
{
let host_handle = 0 as *const c_void;
let host_handle_ref = &host_handle as *const *const c_void;
let domain_id = 0 as c_uint;
let domain_id_ref = &domain_id as *const c_uint;
let exe_path_raw = to_c_str(exe_path);
let app_domain_friendly_name_raw = to_c_str(app_domain_friendly_name);
let properties = properties_option.unwrap_or_else(HashMap::new);
let properties_count = properties.len() as c_int;
let properties_keys: Vec<*const c_char> = properties.keys()
.map(|&k| to_c_str(k))
.collect();
let properties_values: Vec<*const c_char> = properties.values()
.map(|&v| to_c_str(v))
.collect();
let properties_keys_ref = properties_keys.as_ptr();
let properties_values_ref = properties_values.as_ptr();
unsafe {
let coreclr_library = UnixCoreClr::library()?;
let coreclr_initialize: libl::Symbol<CoreClrInitializeFn> = coreclr_library.get(b"coreclr_initialize")?;
match coreclr_initialize(
exe_path_raw,
app_domain_friendly_name_raw,
properties_count,
properties_keys_ref,
properties_values_ref,
host_handle_ref,
domain_id_ref)
{
0 => Ok(UnixCoreClr {
host_handle: host_handle,
domain_id: domain_id
}),
code => panic!("Failed to initialize ({:X}). Host handle: {:?}, domain id: {:?}.", code, host_handle, domain_id)
}
}
}
pub fn shutdown(self: Self) -> io::Result<()> {
unsafe {
let coreclr_library = UnixCoreClr::library()?;
let coreclr_shutdown: libl::Symbol<CoreClrShutdownFn> = coreclr_library.get(b"coreclr_shutdown")?;
match coreclr_shutdown(self.host_handle, self.domain_id) {
0 => Ok(()),
_ => panic!("Failed to shutdown")
}
}
}
pub fn shutdown_2(self: Self) -> io::Result<c_int> {
let latched_exit_code = -1 as c_int;
let latched_exit_code_ref = &latched_exit_code as *const c_int;
unsafe {
let coreclr_library = UnixCoreClr::library()?;
let coreclr_shutdown_2: libl::Symbol<CoreClrShutdown2Fn> = coreclr_library.get(b"coreclr_shutdown_2")?;
match coreclr_shutdown_2(self.host_handle, self.domain_id, latched_exit_code_ref) {
0 => Ok(latched_exit_code),
_ => panic!("Failed to shutdown")
}
}
}
pub fn create_raw_delegate(
self: &Self,
entry_point_assembly_name: &str,
entry_point_type_name: &str,
entry_point_method_name: &str) -> io::Result<*const c_void>
{
let coreclr_delegate = 0 as *const c_void;
let coreclr_delegate_ref = &coreclr_delegate as *const *const c_void;
unsafe {
let coreclr_library = UnixCoreClr::library()?;
let coreclr_create_delegate: libl::Symbol<CoreClrCreateDelegateFn> = coreclr_library.get(b"coreclr_create_delegate")?;
match coreclr_create_delegate(
self.host_handle,
self.domain_id,
to_c_str(entry_point_assembly_name),
to_c_str(entry_point_type_name),
to_c_str(entry_point_method_name),
coreclr_delegate_ref)
{
0 => Ok(coreclr_delegate),
_ => panic!("Failed to shutdown")
}
}
}
}