Skip to content

Commit 06949c2

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

File tree

2 files changed

+91
-33
lines changed

2 files changed

+91
-33
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
}
@@ -662,39 +751,9 @@ impl InterfaceGenerator<'_> {
662751
"#
663752
);
664753

665-
let mut ret_struct_type = String::new();
666-
if self.gen.return_area_size > 0 {
667-
uwrite!(
668-
ret_struct_type,
669-
r#"
670-
private unsafe struct ReturnArea
671-
{{
672-
private int GetS32(IntPtr ptr, int offset)
673-
{{
674-
var span = new Span<byte>((void*)ptr, {});
675-
676-
return BitConverter.ToInt32(span.Slice(offset, 4));
677-
}}
678-
679-
public string GetUTF8String(IntPtr ptr)
680-
{{
681-
return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
682-
}}
683-
684-
}}
685-
686-
[ThreadStatic]
687-
[FixedAddressValueType]
688-
private static ReturnArea returnArea;
689-
"#,
690-
self.gen.return_area_size
691-
);
692-
}
693-
694754
uwrite!(
695755
self.csharp_interop_src,
696756
r#"
697-
{ret_struct_type}
698757
internal static unsafe {result_type} {camel_name}({params})
699758
{{
700759
{src}
@@ -1440,7 +1499,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14401499
self.src,
14411500
"
14421501
var {result_var} = {op};
1443-
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
1502+
IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var});"
14441503
);
14451504

14461505
//TODO: Oppertunity to optimize and not reallocate every call
@@ -1449,7 +1508,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14491508
} else {
14501509
results.push(format!("{interop_string}.ToInt32()"));
14511510
}
1452-
results.push(format!("length"));
1511+
results.push(format!("length{result_var}"));
14531512

14541513
self.gen.gen.needs_interop_string = true;
14551514
}

crates/csharp/tests/codegen.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ macro_rules! codegen_test {
5959
"simple-lists",
6060
"small-anonymous",
6161
"smoke-default",
62-
"strings",
6362
"unused-import",
6463
"use-across-interfaces",
6564
"variants",

0 commit comments

Comments
 (0)