Skip to content

Instantly share code, notes, and snippets.

@rbanay
Forked from zah/ImportNim.cs
Last active November 5, 2015 18:17
Show Gist options
  • Save rbanay/8bcc37ad5cb0b6497daf to your computer and use it in GitHub Desktop.
Save rbanay/8bcc37ad5cb0b6497daf to your computer and use it in GitHub Desktop.
NimString in C#
# variant 2) convert the Nim string to a manually managed piece of memory
type
Exported = objec
len: int
data: ptr char # this has to be freed with Nim's `dealloc` proc
proc marshal(x: string): Exported =
result.len = x.len
result.data = create(char, x.len + 1)
copyMem(result.data, cstring(x), x.len + 1)
// but here i am complitly lost what do i use as the buffer: the Exported above?
proc GetPacksPtrNim(parSze: int, PackArrINOUT: var DataPackArr){.exportc,dynlib.} =
PackArrINOUT.newSeq(parSze)
var dummy:string ="abcdefghij"
for i, curDataPack in PackArrINOUT.mpairs:
# here i generate value by adding the iterator i to the buffer so i will know for sure it's new values on each element
curDataPack = DataPack(buffer:dummy & $i, intVal: uint32 i)
#and it's the simulation of putting any kind of unknown length string from a file or database...
#that is why i bother with the trailing char(i + int8'0')
// variant 1) directly exposing the Nim string type to C#
...
[StructLayout(LayoutKind.Sequential)]
public struct NimString
{
public uint Len;
public uint Capacity;
public LPStr Text;
}
...
[StructLayout(LayoutKind.Sequential)]
public struct TestC
{
public uint Id;
public NimString Str;
}
// variant 2) converting strings to manually managed memory before passing them to C#
// my Version so far
[StructLayout(LayoutKind.Sequential)]
public struct NimString
{
public uint Len;
public uint Capacity;
public char* Text;
}
[StructLayout(LayoutKind.Sequential)]
public struct TestNimStr
{
public uint Id;
public NimString Str;
}
//iterop Signature
[DllImport(@"G:\RobDev\Documents\Visual Studio 2010\Projects\CPP_Interaction\Nim\x64\testnimatom.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void GetPacksPtrNim(int size, TestNimStr** outPackArr);
//this is how i return from Nim
public static unsafe List<TestNimStr> PopulateLstPackCharNim(int ArrL)
{
TestNimStr* PackUArrOut = null;
List<TestNimStr> RtPackLst = new List<TestNimStr>(ArrL);
GetPacksPtrNim(ArrL, &PackUArrOut);
TestNimStr* CurrentPack = PackUArrOut;
for (int i = 0; i < ArrL; i++, CurrentPack++)
{
// here it was simple ..where Strval is IntPtr later i marahsll it... so it actually also two steps
//with the original DataPack-IntPtr member
RtPackLst.Add(new TestNimStr() { StrVal = CurrentPack->StrVal, IntVal = CurrentPack->IntVal });
string accessedElementStr = Marshal.PtrToStringAnsi(RtPackLst.element(number).Strval);
// but how do i access here so there's actually no extra steps in your approach i realise while writing
RtPackLst.Add(new TestNimStr() { Str = CurrentPack->Str, Id = CurrentPack->IntVal });
// Which is NimString struct
var testAccessStructAsString = RtPackLst.element(number).Str;
//so actually: as string ---v method likes it |------v (is a char*)
string buildTheString = new string(RtPackLst.element(number).Str.Text)
}
return RtPackLst;
}
@rbanay
Copy link
Author

rbanay commented Nov 5, 2015

this was actually simple(C# side), i will now try to work on the complete implementation of your approach on the nim side

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment