Skip to content

Commit

Permalink
Merge pull request #18 from Digital-512/patch-1
Browse files Browse the repository at this point in the history
Added an example for C#
  • Loading branch information
vladimirvivien committed Jan 8, 2020
2 parents 4e860f9 + a62b1d2 commit e4ef2ea
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 2 deletions.
80 changes: 78 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,6 @@ Hello LUA!
The following example was contributed by [@r9y9](https://github.com/r9y9). It shows how to invoke exported Go functions from the Julia language. As [documented here](https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/), Julia has the capabilities to invoke exported functions from shared libraries similar to other languages discussed here.
File [client.jl](./client.jl)
```julia
struct GoSlice
arr::Ptr{Void}
Expand Down Expand Up @@ -703,7 +702,6 @@ Hello from Julia!
The following example was contributed by @dpurfield. It shows how to invoke exported Go functions from the Dart language. As documented [here](https://dart.dev/guides/libraries/c-interop), Dart has the capability to invoke exported functions from shared libraries similar to other languages discussed here.
File [client.dart](./client.dart)
```dart
import 'dart:convert';
import 'dart:ffi';
Expand Down Expand Up @@ -815,6 +813,84 @@ void main(List<String> args) {
stdin.readByteSync();
}
```
## From C#
To call the exported Go functions from C# we use the [DllImportAttribute](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportattribute?view=netframework-4.8) attribute to dynamically load and call exported Go functions in the awesome.so shared object file as shown in the following snippet.
File [client.cs](./client.cs)
```cs
using System;
using System.Runtime.InteropServices;

class Awesome
{
const string libName = "awesome.so";

public struct GoSlice
{
public IntPtr data;
public long len, cap;
public GoSlice(IntPtr data, long len, long cap)
{
this.data = data;
this.len = len;
this.cap = cap;
}
}
public struct GoString
{
public string msg;
public long len;
public GoString(string msg, long len)
{
this.msg = msg;
this.len = len;
}
}

// Use DllImport to import the Awesome lib.
[DllImport(libName)]
public static extern int Add(long a, long b);

[DllImport(libName)]
public static extern double Cosine(double a);

[DllImport(libName)]
public static extern void Sort(GoSlice a);

[DllImport(libName, CharSet = CharSet.Unicode)]
public static extern void Log(GoString msg);

static void Main()
{
long add = Add(12, 99);
double cosine = Cosine(1);

long[] data = { 77, 12, 5, 99, 28, 23 };
IntPtr data_ptr = Marshal.AllocHGlobal(Buffer.ByteLength(data));
Marshal.Copy(data, 0, data_ptr, data.Length);
var nums = new GoSlice(data_ptr, data.Length, data.Length);
Sort(nums);
Marshal.Copy(nums.data, data, 0, data.Length);

string msg = "Hello from C#!";
GoString str = new GoString(msg, msg.Length);

Console.WriteLine("awesome.Add(12,99) = " + add);
Console.WriteLine("awesome.Cosine(1) = " + cosine);
Console.WriteLine("awesome.Sort(77,12,5,99,28,23): " + string.Join(", ", data));
Log(str);
}
}
```
When the example is executed, it produces the following:
```
> dotnet run
awesome.Add(12,99) = 111
awesome.Cosine(1) = 0,5403023058681398
awesome.Sort(77,12,5,99,28,23): 5, 12, 23, 28, 77, 99
Hello from C#!
```
## Conclusion
This repo shows how to create a Go library that can be used from C, Python, Ruby, Node, Java, Lua, Julia. By compiling Go packages into C-style shared libraries, Go programmers have a powerful way of integrating their code with any modern language that supports dynamic loading and linking of shared object files.
63 changes: 63 additions & 0 deletions client.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Runtime.InteropServices;

class Awesome
{
const string libName = "awesome.so";

public struct GoSlice
{
public IntPtr data;
public long len, cap;
public GoSlice(IntPtr data, long len, long cap)
{
this.data = data;
this.len = len;
this.cap = cap;
}
}
public struct GoString
{
public string msg;
public long len;
public GoString(string msg, long len)
{
this.msg = msg;
this.len = len;
}
}

// Use DllImport to import the Awesome lib.
[DllImport(libName)]
public static extern int Add(long a, long b);

[DllImport(libName)]
public static extern double Cosine(double a);

[DllImport(libName)]
public static extern void Sort(GoSlice a);

[DllImport(libName, CharSet = CharSet.Unicode)]
public static extern void Log(GoString msg);

static void Main()
{
long add = Add(12, 99);
double cosine = Cosine(1);

long[] data = { 77, 12, 5, 99, 28, 23 };
IntPtr data_ptr = Marshal.AllocHGlobal(Buffer.ByteLength(data));
Marshal.Copy(data, 0, data_ptr, data.Length);
var nums = new GoSlice(data_ptr, data.Length, data.Length);
Sort(nums);
Marshal.Copy(nums.data, data, 0, data.Length);

string msg = "Hello from C#!";
GoString str = new GoString(msg, msg.Length);

Console.WriteLine("awesome.Add(12,99) = " + add);
Console.WriteLine("awesome.Cosine(1) = " + cosine);
Console.WriteLine("awesome.Sort(77,12,5,99,28,23): " + string.Join(", ", data));
Log(str);
}
}

0 comments on commit e4ef2ea

Please sign in to comment.