Intro
This time, I will call some Go functions from C#.
To do this, I should generate a Go dll file and call it from C#.
Calling with int values
First, I will try sending an int value as an argument of a Go funtion and receiving int value from it.
[C#] CallSample.cs
usingSystem.Runtime.InteropServices;namespaceCallDllSample;publicclassCallSample{[DllImport("dllsample")]privatestaticexternintCallInt(intnum);publicintCallGoInt(intnum){returnCallInt(num);}}
[Go] main.go
packagemainimport"C"funcmain(){}// publish functions by "//export ~"//export CallIntfuncCallInt(numint)int{returnnum+3}
Build a dll file
go build -buildmode=c-shared -o dllsample.dll .
Calling with string values
Because C#'s string type and Go's string type are not compatible, these codes cause an exception.
[C#] CallSample.cs
...[DllImport("dllsample")]privatestaticexternstringCallString(stringtext);...publicstringCallGoString(stringtext){returnCallString(text);}}
[Go] main.go
...// DON'T DO THIS//export CallStringfuncCallString(textstring)string{returnfmt.Sprintf("%s World!",text)}
Result
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.Repeat 2 times:-------------------------------- at CallDllSample.CallSample.CallString(System.String)-------------------------------- at CallDllSample.CallSample.CallGoString(System.String) at Program.<Main>$(System.String[])
To resolve that, I have to use "C.char".
[C#] CallSample.cs
...[DllImport("dllsample")]privatestaticexternIntPtrCallString(stringtext);...publicstringCallGoString(stringtext){varresult=CallString(text);Console.WriteLine(result);returnMarshal.PtrToStringAnsi(result)??"";}}
[Go] main.go
...//export CallStringfuncCallString(text*C.char)*C.char{gs:=C.GoString(text)returnC.CString(fmt.Sprintf("%s World!",gs))}
- cgo common - cmd/cgo - Go Packages
- How to call go from c with string (char *) as the parameter without making a copy - GitHub
- GoからCのライブラリを呼ぶ - Qiita
Calling with arrays
To send int array to the Go function, I should convert it to IntPtr.
And to receive int array from the Go function, I should convert from IntPtr.
[C#] CallSample.cs
...publicvoidCallGoArray(){// Convert from C# int array to IntPtrvarnums=newint[]{4,2,5,8};IntPtrintPtr=Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int))*nums.Length);Marshal.Copy(nums,0,intPtr,nums.Length);varpointerResult=CallArray(intPtr,nums.Length);// Convert from IntPtr to C# int arrayvarresults=newint[nums.Length];Marshal.Copy(pointerResult,results,0,results.Length);for(vari=0;i<results.Length;i++){Console.WriteLine($"From Go Index:{i} Value:{results[i]}");}}...
[Go] main.go
...//export CallArrayfuncCallArray(values*C.int,lengthC.int)*C.int{// Convert from C int array to Go int arraycInts:=(*[1<<30]C.int)(unsafe.Pointer(values))[:length:length]goResults:=make([]int,int(length))fori,v:=rangecInts{goResults[i]=int(v)log.Printf("From C# Index: %d Value: %d",int(i),int(v))}// Convert from Go int array to C int arrayresults:=C.malloc(C.size_t(length)*C.size_t(unsafe.Sizeof(uintptr(0))))pointerResult:=(*[1<<30]C.int)(results)fori:=0;i<int(length);i++{pointerResult[i]=C.int(goResults[i]+2)}return(*C.int)(results)}
Top comments(0)
Subscribe
For further actions, you may consider blocking this person and/orreporting abuse