From 63978ffd76975b0fb97f0e1c9fce9d0d62a741d2 Mon Sep 17 00:00:00 2001 From: partic <1596067968@qq.com> Date: Mon, 7 Aug 2023 11:44:56 +0800 Subject: [PATCH] c# backend fix --- csharp/dotnet/pxprpc/BoundMethodCallable .cs | 14 +- csharp/dotnet/pxprpc/BuiltInFuncList.cs | 4 +- .../{AbstractCallable.cs => MethodCallable.cs} | 162 ++++++++++++++------- csharp/dotnet/pxprpc/{Ref.cs => PxpObject.cs} | 6 +- csharp/dotnet/pxprpc/ServerContext.cs | 12 +- csharp/dotnet/pxprpc/tests/TestMain.cs | 22 ++- python/pxprpc/tests.py | 15 +- 7 files changed, 160 insertions(+), 75 deletions(-) rename csharp/dotnet/pxprpc/{AbstractCallable.cs => MethodCallable.cs} (59%) rename csharp/dotnet/pxprpc/{Ref.cs => PxpObject.cs} (86%) diff --git a/csharp/dotnet/pxprpc/BoundMethodCallable .cs b/csharp/dotnet/pxprpc/BoundMethodCallable .cs index 68212cf..976d49e 100644 --- a/csharp/dotnet/pxprpc/BoundMethodCallable .cs +++ b/csharp/dotnet/pxprpc/BoundMethodCallable .cs @@ -36,12 +36,20 @@ namespace pxprpc { args[0] = asyncRet; } - result = method.Invoke(this.boundObj, args); - if (firstInputParamIndex == 0) + try { - asyncRet(result); + result = method.Invoke(this.boundObj, args); + if (firstInputParamIndex == 0) + { + asyncRet(result); + } + } + catch (Exception ex) + { + asyncRet(ex.InnerException); } + } } } diff --git a/csharp/dotnet/pxprpc/BuiltInFuncList.cs b/csharp/dotnet/pxprpc/BuiltInFuncList.cs index 9f371d5..a5126ed 100644 --- a/csharp/dotnet/pxprpc/BuiltInFuncList.cs +++ b/csharp/dotnet/pxprpc/BuiltInFuncList.cs @@ -16,7 +16,7 @@ namespace pxprpc { return obj.ToString(); } - public AbstractCallable getMethod(Object obj, String methodName) + public PxpCallable getMethod(Object obj, String methodName) { try { @@ -37,7 +37,7 @@ namespace pxprpc } } - public AbstractCallable getBoundMethod(Object obj, String methodName) + public PxpCallable getBoundMethod(Object obj, String methodName) { try { diff --git a/csharp/dotnet/pxprpc/AbstractCallable.cs b/csharp/dotnet/pxprpc/MethodCallable.cs similarity index 59% rename from csharp/dotnet/pxprpc/AbstractCallable.cs rename to csharp/dotnet/pxprpc/MethodCallable.cs index 540f026..60f1ddc 100644 --- a/csharp/dotnet/pxprpc/AbstractCallable.cs +++ b/csharp/dotnet/pxprpc/MethodCallable.cs @@ -1,21 +1,128 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Text; namespace pxprpc { - public abstract class AbstractCallable : PxpCallable + public class MethodCallable : PxpCallable { - public void writeResult(PxpRequest req) + + + public MethodInfo method; + + public int[] argList; + public int returnType; + + protected int firstInputParamIndex = 0; + + public MethodCallable(MethodInfo method) + { + this.method = method; + var paras = method.GetParameters(); + argList = new int[paras.Length]; + if (paras.Length > 0 && paras[0].ParameterType == typeof(Action)) + { + firstInputParamIndex = 1; + } + for (int i = firstInputParamIndex; i < paras.Length; i++) + { + var pc = paras[i]; + argList[i] = csTypeToSwitchId(pc.ParameterType); + } + returnType = csTypeToSwitchId(method.ReturnType); + } + + + public virtual void readParameter(PxpRequest req) + { + ServerContext c = req.context; + int thisObj = c.readInt32(); + Object[] args = new Object[argList.Length]; + if (firstInputParamIndex >= 1) + { + args[0] = null; + } + for (int i = firstInputParamIndex; i < argList.Length; i++) + { + args[i] = readNext(c, argList[i]); + } + req.parameter = new Object[] { thisObj, args }; + } + + public virtual void call(PxpRequest req, Action asyncRet) { ServerContext ctx = req.context; - if (req.result is Exception) + + Object result = null; + Object[] args = (Object[])((Object[])req.parameter)[1]; + if (firstInputParamIndex >= 1) { - ctx.writeInt32(1); + args[0] = asyncRet; } - else + try + { + result = method.Invoke(ctx.refSlots[(int)((Object[])req.parameter)[0]], args); + if (firstInputParamIndex == 0) + { + asyncRet(result); + } + } + catch(Exception ex) + { + asyncRet(ex.InnerException); + } + } + public virtual void writeResult(PxpRequest req) + { + var ctx = req.context; + var obj = req.result; + switch (returnType) { - ctx.writeInt32(0); + //primitive type + //boolean + case 1: + ctx.writeInt32((Boolean)obj ? 1 : 0); + break; + //byte + case 2: + ctx.writeInt32((Byte)obj); + break; + //short + case 3: + ctx.writeInt32((Int16)obj); + break; + //int + case 4: + ctx.writeInt32((Int32)obj); + break; + //long + case 5: + ctx.writeInt64((Int64)obj); + break; + //float + case 6: + ctx.writeFloat32((Single)obj); + break; + //double + case 7: + ctx.writeFloat64((Double)obj); + break; + //reference type + case 8: + case 9: + if (req.result is Exception) + { + ctx.writeInt32(1); + } + else + { + ctx.writeInt32(0); + } + break; + //processed by callable + default: + throw new NotImplementedException(); } } @@ -98,49 +205,6 @@ namespace pxprpc } } - public void writeNext(ServerContext ctx, int switchId, Object obj, int addrIfRefType) - { - switch (switchId) - { - //primitive type - //boolean - case 1: - ctx.writeInt32((Boolean)obj ? 1 : 0); - break; - //byte - case 2: - ctx.writeInt32((Byte)obj); - break; - //short - case 3: - ctx.writeInt32((Int16)obj); - break; - //int - case 4: - ctx.writeInt32((Int32)obj); - break; - //long - case 5: - ctx.writeInt64((Int64)obj); - break; - //float - case 6: - ctx.writeFloat32((Single)obj); - break; - //double - case 7: - ctx.writeFloat64((Double)obj); - break; - //reference type - case 8: - case 9: - //processed by callable - default: - throw new NotImplementedException(); - } - } - public abstract void readParameter(PxpRequest req); - public abstract void call(PxpRequest req, Action asyncRet); } } diff --git a/csharp/dotnet/pxprpc/Ref.cs b/csharp/dotnet/pxprpc/PxpObject.cs similarity index 86% rename from csharp/dotnet/pxprpc/Ref.cs rename to csharp/dotnet/pxprpc/PxpObject.cs index 9338421..28c49c0 100644 --- a/csharp/dotnet/pxprpc/Ref.cs +++ b/csharp/dotnet/pxprpc/PxpObject.cs @@ -5,14 +5,14 @@ using System.Text; namespace pxprpc { - public class Ref : IDisposable + public class PxpObject : IDisposable { protected int count; protected Object content; - public Ref() + public PxpObject() { } - public Ref(Object c) + public PxpObject(Object c) { this.count = 0; this.content = c; diff --git a/csharp/dotnet/pxprpc/ServerContext.cs b/csharp/dotnet/pxprpc/ServerContext.cs index a25074d..8e3d450 100644 --- a/csharp/dotnet/pxprpc/ServerContext.cs +++ b/csharp/dotnet/pxprpc/ServerContext.cs @@ -10,7 +10,7 @@ namespace pxprpc { public Stream stream; public static int DefaultRefSlotsCap = 256; - public Ref[] refSlots = new Ref[256]; + public PxpObject[] refSlots = new PxpObject[256]; public Dictionary funcMap = new Dictionary(); protected BuiltInFuncList builtIn; public void init(Stream stream) @@ -21,7 +21,7 @@ namespace pxprpc } public bool running = true; - protected void putRefSlots(int addr, Ref r) + protected void putRefSlots(int addr, PxpObject r) { if (refSlots[addr] != null) refSlots[addr].release(); @@ -36,7 +36,7 @@ namespace pxprpc } public void push(PxpRequest r) { - putRefSlots(r.destAddr, new Ref(r.parameter)); + putRefSlots(r.destAddr, new PxpObject(r.parameter)); writeLock().WaitOne(); this.stream.Write(r.session); writeLock().ReleaseMutex(); @@ -93,7 +93,7 @@ namespace pxprpc { r.result = result; - putRefSlots(r.destAddr, new Ref(result)); + putRefSlots(r.destAddr, new PxpObject(result)); r.pending = false; writeLock().WaitOne(); stream.Write(r.session); @@ -207,7 +207,7 @@ namespace pxprpc String ns = name.Substring(0, namespaceDelim); String func = name.Substring(namespaceDelim + 1); Object obj = funcMap[ns]; - AbstractCallable found = null; + PxpCallable found = null; if (obj != null) { found = builtIn.getBoundMethod(obj, func); @@ -222,7 +222,7 @@ namespace pxprpc } else { - putRefSlots(r.destAddr, new Ref(found)); + putRefSlots(r.destAddr, new PxpObject(found)); this.stream.Write(r.session); diff --git a/csharp/dotnet/pxprpc/tests/TestMain.cs b/csharp/dotnet/pxprpc/tests/TestMain.cs index 9556546..9d79b83 100644 --- a/csharp/dotnet/pxprpc/tests/TestMain.cs +++ b/csharp/dotnet/pxprpc/tests/TestMain.cs @@ -8,21 +8,37 @@ using pxprpc.backend; namespace pxprpc.tests { class TestFuncMap{ + public string get1234() + { + return "1234"; + } public void printString(string s) { Console.WriteLine(s); } - public void printStringUnderline(string s) + public void wait1Sec(Action done) + { + var tim=new System.Timers.Timer(1000); + tim.AutoReset = false; + tim.Elapsed += (object sender, System.Timers.ElapsedEventArgs e) => + { + done(null); + }; + tim.Start(); + } + public string raiseError1() { - Console.WriteLine("__"+s); + throw new Exception("dummy io error"); } + + } public class TestMain { public static void Main(string[] args) { TcpBackend tcp = new TcpBackend(); - tcp.funcMap["test"] = new TestFuncMap(); + tcp.funcMap["test1"] = new TestFuncMap(); tcp.bindAddr = "0.0.0.0:2050"; tcp.listenAndServe(); } diff --git a/python/pxprpc/tests.py b/python/pxprpc/tests.py index 483898b..c657967 100644 --- a/python/pxprpc/tests.py +++ b/python/pxprpc/tests.py @@ -16,6 +16,7 @@ logging.basicConfig(level=logging.INFO) EnableWebsocketServer=False +EnableCSharpClient=False funcMap=dict() @@ -74,6 +75,8 @@ async def amain(): await testClient(client1.rpcconn,'python local pxprpc') + if EnableCSharpClient: + await cstestmain() if EnableWebsocketServer: await wstunnel4test() @@ -129,19 +132,13 @@ async def cstestmain(): client1=pxprpc.backend.TcpClient('127.0.0.1',2050) await client1.start() print('start client') - client2=pxprpc.client.RpcExtendClient1(client1.rpcconn) - t1=await client2.getFunc('test.printString') - print('printString:',t1.value) - t1.signature('b->b') - print(await t1(b'12345')) - t1=await client2.getFunc('test.printStringUnderline') - print('printStringUnderline:',t1.value) - t1.signature('b->b') - print(await t1(b'45678')) + await testClient(client1.rpcconn,'c# test') import sys if __name__=='__main__': if 'enable-websocket-server' in sys.argv: EnableWebsocketServer=True + if 'enable-csharp-client' in sys.argv: + EnableCSharpClient=True asyncio.run(amain()) \ No newline at end of file -- 2.11.4.GIT