Skip to content

Instantly share code, notes, and snippets.

@dstpierre
Created September 30, 2018 11:43
Show Gist options
  • Select an option

  • Save dstpierre/8eec3061ace69716f0ddb01dfd4d8bef to your computer and use it in GitHub Desktop.

Select an option

Save dstpierre/8eec3061ace69716f0ddb01dfd4d8bef to your computer and use it in GitHub Desktop.
Prototype call C# methods from Go using stdin/stdout and a C# wrapper around the libraries
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Your.Library.Here;
namespace ProtoDLLBridge
{
internal class DLLLoader
{
Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
internal bool TryFindType(string typeName, out Type t)
{
lock (typeCache)
{
if (!typeCache.TryGetValue(typeName, out t))
{
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
t = a.GetType(typeName);
if (t != null)
break;
}
typeCache[typeName] = t; // perhaps null
}
}
return t != null;
}
internal object Run(Type t, string f, object[] parameters)
{
var instance = Activator.CreateInstance(t);
MethodInfo mi = t.GetMethod(f);
var safeParameters = new List<object>();
foreach (var p in parameters)
{
if (p.GetType() == typeof(Int64))
{
safeParameters.Add(Convert.ToInt32(p.ToString()));
}
else
{
safeParameters.Add(p);
}
}
return mi.Invoke(instance, safeParameters.ToArray());
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProtoDLLBridge
{
internal class InputParser
{
public string TypeName { get; set; }
public string FunctionName { get; set; }
public object[] Parameters { get; set; }
internal static InputParser Eval(string json)
{
var input = Newtonsoft.Json.JsonConvert.DeserializeObject<InputParser>(json);
return input;
}
}
}
package main
import (
"bufio"
"io"
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("./ProtoDLLBridge/bin/debug/ProtoDLLBridge.exe")
cmd.Stderr = os.Stderr
stdin, err := cmd.StdinPipe()
if nil != err {
log.Fatalf("Error obtaining stdin: %s", err.Error())
}
stdout, err := cmd.StdoutPipe()
if nil != err {
log.Fatalf("Error obtaining stdout: %s", err.Error())
}
reader := bufio.NewReader(stdout)
go func(reader io.Reader) {
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
log.Printf("Reading from subprocess: %s", scanner.Text())
}
}(reader)
if err := cmd.Start(); nil != err {
log.Fatalf("Error starting program: %s, %s", cmd.Path, err.Error())
}
stdin.Write([]byte(`{"typename": "Your.Library.Here.OrderService", "functionname": "FetchForWork", "parameters": [877542]}` + "\n"))
cmd.Wait()
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Your.Library.Here;
namespace ProtoDLLBridge
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("started");
var dll = new DLLLoader();
var input = new InputParser();
while (true)
{
input = new InputParser();
var json = Console.ReadLine();
try
{
input = InputParser.Eval(json);
}
catch (Exception ex)
{
Console.WriteLine(string.Format("{\"error\": true, \"msg\": \"{0}\"}", ex.Message));
continue;
}
Type t;
if (dll.TryFindType(input.TypeName, out t))
{
var result = dll.Run(t, input.FunctionName, input.Parameters);
var resultJson = Newtonsoft.Json.JsonConvert.SerializeObject(result);
Console.WriteLine(resultJson);
}
else
{
Console.WriteLine("null");
}
}
Console.ReadLine();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment