Created
March 20, 2024 12:01
-
-
Save Sharp0802/ed24e57528db4c41b2d768c9deee81a8 to your computer and use it in GitHub Desktop.
Interop std::string to C++ from C# with P/Invoke
This file contains hidden or 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
#include <string> | |
#include <iostream> | |
void WriteLine(std::string str) | |
{ | |
std::cout << str << std::endl << std::flush; | |
} |
This file contains hidden or 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
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
unsafe | |
{ | |
var ns = new NativeString("Hello from C++!"); | |
WriteLine(&ns); | |
} | |
[DllImport("./main.so", EntryPoint = "_Z9WriteLineNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE", ExactSpelling = true)] | |
static extern unsafe void WriteLine(NativeString* str); | |
[Serializable] | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct NativeString : IDisposable | |
{ | |
[StructLayout(LayoutKind.Explicit)] | |
private struct LocalBuffer | |
{ | |
[FieldOffset(0)] public ulong Capacity; | |
[FieldOffset(0)] public unsafe fixed byte Buffer[16]; | |
} | |
public NativeString(string str) | |
{ | |
unsafe | |
{ | |
_length = (ulong)Encoding.UTF8.GetByteCount(str); | |
_localBuffer.Capacity = (_length * 2) | 1; | |
_buffer = (byte*)NativeMemory.Alloc((UIntPtr)_localBuffer.Capacity); | |
fixed (byte* p = Encoding.UTF8.GetBytes(str)) | |
Unsafe.CopyBlock(_buffer, p, (uint)_length); | |
_buffer[_length] = 0; | |
} | |
} | |
private unsafe byte* _buffer; | |
private ulong _length; | |
private LocalBuffer _localBuffer; | |
public int Length => checked((int)_length); | |
public static implicit operator NativeString(string str) => new(str); | |
public override string ToString() | |
{ | |
unsafe | |
{ | |
return Marshal.PtrToStringUTF8((IntPtr)_buffer) | |
?? throw new InvalidOperationException(); | |
} | |
} | |
public void Dispose() | |
{ | |
unsafe | |
{ | |
NativeMemory.Free(_buffer); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment