From 4fcacbd5641fef86d8822beda9655c57848d78a9 Mon Sep 17 00:00:00 2001 From: Koncord Date: Sun, 23 Dec 2018 05:25:17 +0800 Subject: [PATCH] first commit --- README | 3 + csharp/Functions/Public.cs | 13 +++ csharp/Functions/Timer.cs | 34 ++++++ csharp/Instance.cs | 183 ++++++++++++++++++++++++++++++ csharp/Makefile | 11 ++ csharp/Properties/AssemblyInfo.cs | 35 ++++++ genFnClass.py | 61 ++++++++++ genFnClasses.py | 19 ++++ helper.py | 64 +++++++++++ requirements.txt | 2 + 10 files changed, 425 insertions(+) create mode 100644 README create mode 100644 csharp/Functions/Public.cs create mode 100644 csharp/Functions/Timer.cs create mode 100644 csharp/Instance.cs create mode 100644 csharp/Makefile create mode 100644 csharp/Properties/AssemblyInfo.cs create mode 100644 genFnClass.py create mode 100644 genFnClasses.py create mode 100644 helper.py create mode 100644 requirements.txt diff --git a/README b/README new file mode 100644 index 0000000..c05064e --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +NetLibGen +--------- +This is an experimental tes3mp C# bindings generator diff --git a/csharp/Functions/Public.cs b/csharp/Functions/Public.cs new file mode 100644 index 0000000..133e23e --- /dev/null +++ b/csharp/Functions/Public.cs @@ -0,0 +1,13 @@ +using System.Runtime.CompilerServices; + +namespace TES3MPSharp +{ + public static partial class TES3MP + { + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void MakePublic(object callback, string name); + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern object CallPublic(string name, params object[] args); + } +} diff --git a/csharp/Functions/Timer.cs b/csharp/Functions/Timer.cs new file mode 100644 index 0000000..669f64a --- /dev/null +++ b/csharp/Functions/Timer.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + + +namespace TES3MPSharp +{ + public static partial class TES3MP + { + public static int CreateTimer(object callback, int msec) + { + return CreateTimerEx(callback, msec, ""); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern int CreateTimerEx(object callback, int msec, string types, params object[] args); + + + [DllImport("__Internal", CharSet = CharSet.Ansi)] + public static extern void StartTimer(int timerId); + + [DllImport("__Internal", CharSet = CharSet.Ansi)] + public static extern void StopTimer(int timerId); + + [DllImport("__Internal", CharSet = CharSet.Ansi)] + public static extern void RestartTimer(int timerId, int msec); + + [DllImport("__Internal", CharSet = CharSet.Ansi)] + public static extern void FreeTimer(int timerId); + + [DllImport("__Internal", CharSet = CharSet.Ansi)] + public static extern bool IsTimerElapsed(int timerId); + } +} diff --git a/csharp/Instance.cs b/csharp/Instance.cs new file mode 100644 index 0000000..c41ac99 --- /dev/null +++ b/csharp/Instance.cs @@ -0,0 +1,183 @@ +using System; + +namespace TES3MPSharp +{ + public class Instance + { + public virtual void OnServerInit() + { + } + public virtual void OnServerPostInit() + { + } + public virtual void OnServerExit(int code) + { + } + public virtual void OnPlayerConnect(ushort pid) + { + } + public virtual void OnPlayerDisconnect(ushort pid) + { + } + public virtual void OnPlayerDeath(ushort pid) + { + } + public virtual void OnPlayerResurrect(ushort pid) + { + } + public virtual void OnPlayerCellChange(ushort pid) + { + } + public virtual void OnPlayerAttribute(ushort pid) + { + } + public virtual void OnPlayerSkill(ushort pid) + { + } + public virtual void OnPlayerLevel(ushort pid) + { + } + public virtual void OnPlayerBounty(ushort pid) + { + } + public virtual void OnPlayerReputation(ushort pid) + { + } + public virtual void OnPlayerEquipment(ushort pid) + { + } + public virtual void OnPlayerInventory(ushort pid) + { + } + public virtual void OnPlayerJournal(ushort pid) + { + } + public virtual void OnPlayerFaction(ushort pid) + { + } + public virtual void OnPlayerShapeshift(ushort pid) + { + } + public virtual void OnPlayerSpellbook(ushort pid) + { + } + public virtual void OnPlayerQuickKeys(ushort pid) + { + } + public virtual void OnPlayerTopic(ushort pid) + { + } + public virtual void OnPlayerDisposition(ushort pid) + { + } + public virtual void OnPlayerBook(ushort pid) + { + } + public virtual void OnPlayerItemUse(ushort pid) + { + } + public virtual void OnPlayerMiscellaneous(ushort pid) + { + } + public virtual void OnPlayerInput(ushort pid) + { + } + public virtual void OnPlayerRest(ushort pid) + { + } + public virtual void OnPlayerSendMessage(ushort pid, string message) + { + } + public virtual void OnPlayerEndCharGen(ushort pid) + { + } + + public virtual void OnGUIAction(ushort pid, int idGui, string data) + { + } + + public virtual void OnRecordDynamic(ushort pid) + { + } + + public virtual void OnCellLoad(ushort pid, string cellDescription) + { + } + public virtual void OnCellUnload(ushort pid, string cellDescription) + { + } + public virtual void OnCellDeletion(string cellDescription) + { + } + + public virtual void OnContainer(ushort pid, string cellDescription) + { + } + public virtual void OnDoorState(ushort pid, string cellDescription) + { + } + public virtual void OnObjectActivate(ushort pid, string cellDescription) + { + } + public virtual void OnObjectPlace(ushort pid, string cellDescription) + { + } + public virtual void OnObjectState(ushort pid, string cellDescription) + { + } + public virtual void OnObjectSpawn(ushort pid, string cellDescription) + { + } + public virtual void OnObjectDelete(ushort pid, string cellDescription) + { + } + public virtual void OnObjectLock(ushort pid, string cellDescription) + { + } + public virtual void OnObjectScale(ushort pid, string cellDescription) + { + } + public virtual void OnObjectTrap(ushort pid, string cellDescription) + { + } + public virtual void OnVideoPlay(ushort pid, string cellDescription) + { + } + + public virtual void OnActorList(ushort pid, string cellDescription) + { + } + public virtual void OnActorEquipment(ushort pid, string cellDescription) + { + } + public virtual void OnActorAI(ushort pid, string cellDescription) + { + } + public virtual void OnActorDeath(ushort pid, string cellDescription) + { + } + public virtual void OnActorCellChange(ushort pid, string cellDescription) + { + } + public virtual void OnActorTest(ushort pid, string cellDescription) + { + } + + public virtual void OnWorldKillCount(ushort pid) + { + } + public virtual void OnWorldMap(ushort pid) + { + } + public virtual void OnWorldWeather(ushort pid) + { + } + + public virtual void OnMpNumIncrement(int mpNum) + { + } + public virtual void OnRequestPluginList() + { + } + } +} diff --git a/csharp/Makefile b/csharp/Makefile new file mode 100644 index 0000000..d954f05 --- /dev/null +++ b/csharp/Makefile @@ -0,0 +1,11 @@ +files := Instance.cs Properties/AssemblyInfo.cs $(wildcard ./Functions/*.cs) $(wildcard ./Functions.Generated/*.cs) + +all: TES3MPSharp.dll + +TES3MPSharp.dll: $(files) + @mcs -out:TES3MPSharp.dll -target:library $(files) + +clean: + @rm -f TES3MPSharp.dll + +.PHONY: all clean run diff --git a/csharp/Properties/AssemblyInfo.cs b/csharp/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d067f42 --- /dev/null +++ b/csharp/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TES3MPSharp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TES3MPSharp")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("86F11AE4-07E5-468B-A8B1-50504791F14E")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/genFnClass.py b/genFnClass.py new file mode 100644 index 0000000..bfb75b1 --- /dev/null +++ b/genFnClass.py @@ -0,0 +1,61 @@ +import os +import sys +from helper import * + +Config.set_library_path('/usr/lib/llvm-6.0/lib') + + +def createCsharpFile(csharpNamespace: str, cppFilename: str, csharpFilename: str): + index = Index.create() + tu = index.parse(cppFilename) + funcs, classes, namespaces = find_decls(tu) + + csharpFile = open(csharpFilename, "w") + + csharpFile.write('using System.Runtime.InteropServices;\n\n') + csharpFile.write('namespace {0}\n{{\n'.format(csharpNamespace)) + + # csharpFile.write(' public static class {0}\n {{\n'.format(u.spelling)) + csharpFile.write(' public static partial class {0}\n {{\n'.format('TES3MP')) + + for c in funcs: + + if c.kind == CursorKind.FUNCTION_DECL: + funcName = c.spelling + funcType = convertType(c.result_type.kind) + #csharpFile.write(' [MethodImpl(MethodImplOptions.InternalCall)]\n') + csharpFile.write(' [DllImport("__Internal", CharSet = CharSet.Ansi)]\n') + csharpFile.write(' public static extern {0} {1}('.format(funcType, funcName)) + + args = '' + for par in get_params(c): + isPtr = False + typ = par[0] + argName = par[-1] + if typ == TypeKind.POINTER: + isPtr = True + typ = par[1] + argType = convertType(typ, isPtr) + args += '{0} {1}, '.format(argType, argName) + + csharpFile.write(args[:-2] + ');\n\n') + + csharpFile.write(' }\n') + csharpFile.write('}') + csharpFile.close() + + +if __name__ == '__main__': + if len(sys.argv) < 3: + print(sys.argv[0], "csharp-namespace cpp-file [csharp-file]") + sys.exit() + + namespace = sys.argv[1] + cppfile = sys.argv[2] + csharpfile = '' + if len(sys.argv) == 3: + csharpfile = cppfile.split(os.sep)[-1].split('.')[0] + '.cs' + else: + csharpfile = sys.argv[3] + + createCsharpFile(namespace, cppfile, csharpfile) diff --git a/genFnClasses.py b/genFnClasses.py new file mode 100644 index 0000000..e2c074f --- /dev/null +++ b/genFnClasses.py @@ -0,0 +1,19 @@ +from genFnClass import createCsharpFile +import sys +from os import listdir, makedirs, path +from os.path import isfile, join +from progressbar import * + +# python ./genFnClasses.py $TES3MP_PATH/apps/openmw-mp/Script/Functions $OUT/lib +if __name__ == '__main__': + cppfilesDir = sys.argv[1] + outdir = sys.argv[2] + hppfiles = [f for f in listdir(cppfilesDir) if isfile(join(cppfilesDir, f)) and f.endswith('.hpp')] + if not path.exists(outdir): + makedirs(outdir) + for i in progressbar(range(len(hppfiles))): + cppfile = join(cppfilesDir, hppfiles[i]) + outfile = join(outdir, hppfiles[i].split('.')[0] + '.cs') + if hppfiles[i] == "Timer.hpp" or hppfiles[i] == "Public.hpp": + continue + createCsharpFile("TES3MPSharp", cppfile, outfile) diff --git a/helper.py b/helper.py new file mode 100644 index 0000000..e98b8c4 --- /dev/null +++ b/helper.py @@ -0,0 +1,64 @@ +from clang.cindex import * + +def find_decls(tu: TranslationUnit): + filename = tu.cursor.spelling + funcs = [] + classes = [] + namespaces = [] + for c in tu.cursor.walk_preorder(): + loc = c.location + if loc.file is None or loc.file.name != filename: + continue + elif c.kind == CursorKind.FUNCTION_DECL: + funcs.append(c) + elif c.kind == CursorKind.CLASS_DECL: + classes.append(c) + elif c.kind == CursorKind.NAMESPACE: + namespaces.append(c) + return funcs, classes, namespaces + + +def get_params(node: Cursor): + # return [[c.type.kind, c.spelling] for c in node.get_children() if c.kind == CursorKind.PARM_DECL] + a = [] + for c in node.get_children(): + if c.kind == CursorKind.PARM_DECL: + t: Type = c.type + if t.kind == TypeKind.POINTER: + ptype = t.get_pointee() + a.append([t.kind, ptype.kind, c.spelling]) + else: + a.append([t.kind, c.spelling]) + return a + + +def convertType(typeKind: TypeKind, isPtr=False) -> str: + if typeKind is TypeKind.VOID: + return 'void' + elif typeKind is TypeKind.BOOL: + return 'bool' + elif typeKind is TypeKind.CHAR_U or typeKind is TypeKind.UCHAR: + return 'byte' + elif typeKind is TypeKind.CHAR_S or typeKind is TypeKind.SCHAR: + if isPtr: + return 'string' + else: + return 'sbyte' + elif typeKind is TypeKind.SHORT: + return 'short' + elif typeKind is TypeKind.USHORT: + return 'ushort' + elif typeKind is TypeKind.UINT: + return 'uint' + elif typeKind is TypeKind.INT: + return 'int' + elif typeKind is TypeKind.ULONG: + return 'ulong' + elif typeKind is TypeKind.LONG: + return 'long' + elif typeKind is TypeKind.FLOAT: + return 'float' + elif typeKind is TypeKind.DOUBLE: + return 'double' + else: + return 'object' # probably will fail \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dbd4d24 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +clang==6.0.0.2 +progressbar2==3.38.0