Skip to content

Commit 902e0e1

Browse files
committed
fix(c#): strings code generation test
Signed-off-by: James Sturtevant <[email protected]>
1 parent b3da31d commit 902e0e1

File tree

2 files changed

+92
-32
lines changed

2 files changed

+92
-32
lines changed

crates/csharp/src/lib.rs

Lines changed: 91 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,42 @@ impl WorldGenerator for CSharp {
145145
gen.import(&resolve.name_world_key(key), func);
146146
}
147147

148+
let mut ret_struct_type = String::new();
149+
if gen.gen.return_area_size > 0 {
150+
uwrite!(
151+
ret_struct_type,
152+
r#"
153+
private unsafe struct ReturnArea
154+
{{
155+
private int GetS32(IntPtr ptr, int offset)
156+
{{
157+
var span = new Span<byte>((void*)ptr, {});
158+
159+
return BitConverter.ToInt32(span.Slice(offset, 4));
160+
}}
161+
162+
public string GetUTF8String(IntPtr ptr)
163+
{{
164+
return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
165+
}}
166+
167+
}}
168+
169+
[ThreadStatic]
170+
[FixedAddressValueType]
171+
private static ReturnArea returnArea;
172+
"#,
173+
gen.gen.return_area_size
174+
);
175+
}
176+
177+
uwrite!(
178+
gen.csharp_interop_src,
179+
r#"
180+
{ret_struct_type}
181+
"#
182+
);
183+
148184
gen.add_interface_fragment(false);
149185
}
150186

@@ -181,6 +217,59 @@ impl WorldGenerator for CSharp {
181217
gen.export(func, Some(key));
182218
}
183219

220+
// Declare a statically-allocated return area, if needed. We only do
221+
// this for export bindings, because import bindings allocate their
222+
// return-area on the stack.
223+
if gen.gen.return_area_size > 0 {
224+
let mut ret_area_str = String::new();
225+
226+
uwrite!(
227+
ret_area_str,
228+
"
229+
[InlineArray({})]
230+
[StructLayout(LayoutKind.Sequential, Pack = {})]
231+
private struct ReturnArea
232+
{{
233+
private byte buffer;
234+
235+
private int GetS32(int offset)
236+
{{
237+
ReadOnlySpan<byte> span = this;
238+
239+
return BitConverter.ToInt32(span.Slice(offset, 4));
240+
}}
241+
242+
public void SetS32(int offset, int value)
243+
{{
244+
Span<byte> span = this;
245+
246+
BitConverter.TryWriteBytes(span.Slice(offset), value);
247+
}}
248+
249+
internal unsafe int AddrOfBuffer()
250+
{{
251+
fixed(byte* ptr = &buffer)
252+
{{
253+
return (int)ptr;
254+
}}
255+
}}
256+
257+
public unsafe string GetUTF8String(int p0, int p1)
258+
{{
259+
return Encoding.UTF8.GetString((byte*)p0, p1);
260+
}}
261+
}}
262+
263+
[ThreadStatic]
264+
private static ReturnArea returnArea = default;
265+
",
266+
gen.gen.return_area_size,
267+
gen.gen.return_area_align,
268+
);
269+
270+
gen.csharp_interop_src.push_str(&ret_area_str);
271+
}
272+
184273
gen.add_interface_fragment(true);
185274
Ok(())
186275
}
@@ -675,39 +764,9 @@ impl InterfaceGenerator<'_> {
675764
"#
676765
);
677766

678-
let mut ret_struct_type = String::new();
679-
if self.gen.return_area_size > 0 {
680-
uwrite!(
681-
ret_struct_type,
682-
r#"
683-
private unsafe struct ReturnArea
684-
{{
685-
private int GetS32(IntPtr ptr, int offset)
686-
{{
687-
var span = new Span<byte>((void*)ptr, {});
688-
689-
return BitConverter.ToInt32(span.Slice(offset, 4));
690-
}}
691-
692-
public string GetUTF8String(IntPtr ptr)
693-
{{
694-
return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
695-
}}
696-
697-
}}
698-
699-
[ThreadStatic]
700-
[FixedAddressValueType]
701-
private static ReturnArea returnArea;
702-
"#,
703-
self.gen.return_area_size
704-
);
705-
}
706-
707767
uwrite!(
708768
self.csharp_interop_src,
709769
r#"
710-
{ret_struct_type}
711770
internal static unsafe {result_type} {camel_name}({params})
712771
{{
713772
{src}
@@ -1458,7 +1517,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14581517
self.src,
14591518
"
14601519
var {result_var} = {op};
1461-
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
1520+
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var});"
14621521
);
14631522

14641523
//TODO: Oppertunity to optimize and not reallocate every call
@@ -1467,7 +1526,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14671526
} else {
14681527
results.push(format!("{interop_string}.ToInt32()"));
14691528
}
1470-
results.push(format!("length"));
1529+
results.push(format!("length{result_var}"));
14711530

14721531
self.gen.gen.needs_interop_string = true;
14731532
}

crates/csharp/tests/codegen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ macro_rules! codegen_test {
5858
"simple-lists",
5959
"small-anonymous",
6060
"strings",
61+
"smoke-default",
6162
"unused-import",
6263
"use-across-interfaces",
6364
"variants",

0 commit comments

Comments
 (0)