diff --git a/cs/ndll/NDLLFunction.hx b/cs/ndll/NDLLFunction.hx new file mode 100644 index 000000000..0c02b325a --- /dev/null +++ b/cs/ndll/NDLLFunction.hx @@ -0,0 +1,15 @@ +package cs.ndll; + +extern class NDLLFunction +{ + static var Initialized(get, never):Bool; + static function Initialize(arrayType:Class, reflectType:Class, functionType:Class, hxObjectype:Class):Void; + static function Load(name:String, func:String, numArgs:Int):Dynamic; + function CallMult(args:Dynamic):Dynamic; + function Call0():Dynamic; + function Call1(arg1:Dynamic):Dynamic; + function Call2(arg1:Dynamic, arg2:Dynamic):Dynamic; + function Call3(arg1:Dynamic, arg2:Dynamic, arg3:Dynamic):Dynamic; + function Call4(arg1:Dynamic, arg2:Dynamic, arg3:Dynamic, arg4:Dynamic):Dynamic; + function Call5(arg1:Dynamic, arg2:Dynamic, arg3:Dynamic, arg4:Dynamic, arg5:Dynamic):Dynamic; +} \ No newline at end of file diff --git a/haxe/Timer.hx b/haxe/Timer.hx index e920a633c..a4b1d05fe 100644 --- a/haxe/Timer.hx +++ b/haxe/Timer.hx @@ -1,5 +1,5 @@ package haxe; -#if (!neko && !cpp && !nodejs) +#if (!neko && !cpp && !nodejs && !cs) // Original haxe.Timer class diff --git a/include.xml b/include.xml index 398eccc3b..ec280f3d7 100644 --- a/include.xml +++ b/include.xml @@ -3,11 +3,12 @@ - - + + + diff --git a/lime/Assets.hx b/lime/Assets.hx index f9d6a3e4b..a9e5e5eb0 100644 --- a/lime/Assets.hx +++ b/lime/Assets.hx @@ -509,7 +509,7 @@ class Assets { private static function isValidImage (buffer:Image):Bool { #if (tools && !display) - #if (cpp || neko || nodejs) + #if lime_cffi return (buffer != null); //return (bitmapData.__handle != null); diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index 2dd6d665f..0bd8a8791 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -131,7 +131,7 @@ class NativeApplication { untyped setImmediate (eventLoop); return 0; - #elseif (cpp || neko) + #elseif (cpp || neko || cs) var result = lime_application_exec (handle); parent.onExit.dispatch (result); diff --git a/lime/audio/AudioBuffer.hx b/lime/audio/AudioBuffer.hx index 709a95ea5..51ab623a8 100644 --- a/lime/audio/AudioBuffer.hx +++ b/lime/audio/AudioBuffer.hx @@ -191,7 +191,7 @@ class AudioBuffer { } - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_audio_load (data:Dynamic):Dynamic; #end diff --git a/lime/audio/AudioSource.hx b/lime/audio/AudioSource.hx index 005d87dd6..340be7001 100644 --- a/lime/audio/AudioSource.hx +++ b/lime/audio/AudioSource.hx @@ -52,7 +52,7 @@ class AudioSource { private var __gain:Float = 1.0; #end - #if (cpp || neko || nodejs) + #if lime_cffi private var timer:Timer; #end diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index a18b5eea5..81f23b3c4 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -1625,7 +1625,7 @@ class Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_image_load (data:Dynamic):Dynamic; #end diff --git a/lime/graphics/cairo/CairoFTFontFace.hx b/lime/graphics/cairo/CairoFTFontFace.hx index 26bd88944..6a7b48c2a 100644 --- a/lime/graphics/cairo/CairoFTFontFace.hx +++ b/lime/graphics/cairo/CairoFTFontFace.hx @@ -40,7 +40,7 @@ abstract CairoFTFontFace(CairoFontFace) from CairoFontFace to CairoFontFace from - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_cairo_ft_font_face_create (face:CFFIPointer, flags:Int):CFFIPointer; #end diff --git a/lime/graphics/cairo/CairoFontFace.hx b/lime/graphics/cairo/CairoFontFace.hx index c66d19936..8d985cc3f 100644 --- a/lime/graphics/cairo/CairoFontFace.hx +++ b/lime/graphics/cairo/CairoFontFace.hx @@ -36,7 +36,7 @@ abstract CairoFontFace(CFFIPointer) from CFFIPointer to CFFIPointer { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_cairo_font_face_status (handle:CFFIPointer):Int; #end diff --git a/lime/graphics/cairo/CairoFontOptions.hx b/lime/graphics/cairo/CairoFontOptions.hx index 58dd2e1c7..c90649e1e 100644 --- a/lime/graphics/cairo/CairoFontOptions.hx +++ b/lime/graphics/cairo/CairoFontOptions.hx @@ -132,7 +132,7 @@ abstract CairoFontOptions(CFFIPointer) from CFFIPointer to CFFIPointer { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_cairo_font_options_create ():CFFIPointer; @:cffi private static function lime_cairo_font_options_get_antialias (handle:CFFIPointer):Int; @:cffi private static function lime_cairo_font_options_get_hint_metrics (handle:CFFIPointer):Int; diff --git a/lime/graphics/format/JPEG.hx b/lime/graphics/format/JPEG.hx index a008f080b..8f85d3ac2 100644 --- a/lime/graphics/format/JPEG.hx +++ b/lime/graphics/format/JPEG.hx @@ -23,7 +23,7 @@ class JPEG { public static function decodeBytes (bytes:Bytes, decodeData:Bool = true):Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var bufferData:Dynamic = lime_jpeg_decode_bytes (bytes, decodeData); @@ -44,7 +44,7 @@ class JPEG { public static function decodeFile (path:String, decodeData:Bool = true):Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var bufferData:Dynamic = lime_jpeg_decode_file (path, decodeData); @@ -120,7 +120,7 @@ class JPEG { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_jpeg_decode_bytes (data:Dynamic, decodeData:Bool):Dynamic; @:cffi private static function lime_jpeg_decode_file (path:String, decodeData:Bool):Dynamic; @:cffi private static function lime_image_encode (data:Dynamic, type:Int, quality:Int):Dynamic; diff --git a/lime/graphics/format/PNG.hx b/lime/graphics/format/PNG.hx index e7bb963a1..b37f259ef 100644 --- a/lime/graphics/format/PNG.hx +++ b/lime/graphics/format/PNG.hx @@ -30,7 +30,7 @@ class PNG { public static function decodeBytes (bytes:Bytes, decodeData:Bool = true):Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var bufferData:Dynamic = lime_png_decode_bytes (bytes, decodeData); @@ -51,7 +51,7 @@ class PNG { public static function decodeFile (path:String, decodeData:Bool = true):Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var bufferData:Dynamic = lime_png_decode_file (path, decodeData); @@ -164,7 +164,7 @@ class PNG { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_png_decode_bytes (data:Dynamic, decodeData:Bool):Dynamic; @:cffi private static function lime_png_decode_file (path:String, decodeData:Bool):Dynamic; @:cffi private static function lime_image_encode (data:Dynamic, type:Int, quality:Int):Dynamic; diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 6dd633e60..4a0688208 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -32,7 +32,7 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_color_transform (image, rect, colorMatrix); else #end { @@ -98,7 +98,7 @@ class ImageDataUtil { if (srcData == null || destData == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else #end { @@ -160,7 +160,7 @@ class ImageDataUtil { public static function copyPixels (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image = null, alphaPoint:Vector2 = null, mergeAlpha:Bool = false):Void { - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); else #end { @@ -326,7 +326,7 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_fill_rect (image, rect, (fillColor >> 16) & 0xFFFF, (fillColor) & 0xFFFF); else // TODO: Better Int32 solution #end { @@ -365,7 +365,7 @@ class ImageDataUtil { if (format == ARGB32) color = ((color & 0xFFFFFF) << 8) | ((color >> 24) & 0xFF); - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_flood_fill (image, x, y, (color >> 16) & 0xFFFF, (color) & 0xFFFF); else // TODO: Better Int32 solution #end { @@ -652,7 +652,7 @@ class ImageDataUtil { var length = Std.int (rect.width * rect.height); var bytes = Bytes.alloc (length * 4); - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_get_pixels (image, rect, format, bytes); else #end { @@ -703,7 +703,7 @@ class ImageDataUtil { if (image.buffer.data == null || sourceImage.buffer.data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); else #end { @@ -757,7 +757,7 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null || !image.buffer.transparent) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_multiply_alpha (image); else #end { @@ -788,7 +788,7 @@ class ImageDataUtil { if (buffer.width == newWidth && buffer.height == newHeight) return; var newBuffer = new ImageBuffer (new UInt8Array (newWidth * newHeight * 4), newWidth, newHeight); - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_resize (image, newBuffer, newWidth, newHeight); else #end { @@ -900,7 +900,7 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_set_format (image, format); else #end { @@ -1036,7 +1036,7 @@ class ImageDataUtil { if (image.buffer.data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_set_pixels (image, rect, bytes, format); else #end { @@ -1129,7 +1129,7 @@ class ImageDataUtil { var hits = 0; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) hits = lime_image_data_util_threshold (image, sourceImage, sourceRect, destPoint, _operation, (_threshold >> 16) & 0xFFFF, (_threshold) & 0xFFFF, (_color >> 16) & 0xFFFF, (_color) & 0xFFFF, (_mask >> 16) & 0xFFFF, (_mask) & 0xFFFF, copySource); else #end { @@ -1142,7 +1142,7 @@ class ImageDataUtil { var srcPremultiplied = sourceImage.buffer.premultiplied; var destPremultiplied = image.buffer.premultiplied; - var srcPosition, destPosition, srcPixel:RGBA, destPixel:RGBA, pixelMask:Int, test:Bool, value:Int; + var srcPosition, destPosition, srcPixel:RGBA, destPixel:RGBA, pixelMask:UInt, test:Bool, value:Int; for (y in 0...destView.height) { @@ -1206,7 +1206,7 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; - #if ((cpp || neko) && !disable_cffi && !macro) + #if (lime_cffi && !disable_cffi && !macro) if (CFFI.enabled) lime_image_data_util_unmultiply_alpha (image); else #end { @@ -1231,10 +1231,10 @@ class ImageDataUtil { } - private static inline function __pixelCompare (n1:Int, n2:Int):Int { + private static inline function __pixelCompare (n1:UInt, n2:UInt):Int { - var tmp1:Int; - var tmp2:Int; + var tmp1:UInt; + var tmp2:UInt; tmp1 = (n1 >> 24) & 0xFF; tmp2 = (n2 >> 24) & 0xFF; @@ -1292,7 +1292,7 @@ class ImageDataUtil { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_image_data_util_color_transform (image:Dynamic, rect:Dynamic, colorMatrix:Dynamic):Void; @:cffi private static function lime_image_data_util_copy_channel (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, srcChannel:Int, destChannel:Int):Void; @:cffi private static function lime_image_data_util_copy_pixels (image:Dynamic, sourceImage:Dynamic, sourceRect:Dynamic, destPoint:Dynamic, alphaImage:Dynamic, alphaPoint:Dynamic, mergeAlpha:Bool):Void; diff --git a/lime/math/color/ARGB.hx b/lime/math/color/ARGB.hx index 1686eb914..90ef6902e 100644 --- a/lime/math/color/ARGB.hx +++ b/lime/math/color/ARGB.hx @@ -6,7 +6,7 @@ import lime.utils.UInt32Array; import lime.utils.UInt8Array; -abstract ARGB(Int) from Int to Int from UInt to UInt { +abstract ARGB(UInt) from Int to Int from UInt to UInt { private static var a16:Int; diff --git a/lime/math/color/BGRA.hx b/lime/math/color/BGRA.hx index f25b810df..607a81dc8 100644 --- a/lime/math/color/BGRA.hx +++ b/lime/math/color/BGRA.hx @@ -6,7 +6,7 @@ import lime.utils.UInt32Array; import lime.utils.UInt8Array; -abstract BGRA(Int) from Int to Int from UInt to UInt { +abstract BGRA(UInt) from Int to Int from UInt to UInt { private static var a16:Int; diff --git a/lime/math/color/RGBA.hx b/lime/math/color/RGBA.hx index 95d88a57f..c89a751b7 100644 --- a/lime/math/color/RGBA.hx +++ b/lime/math/color/RGBA.hx @@ -8,7 +8,7 @@ import lime.utils.UInt8Array; @:allow(lime.math.color) -abstract RGBA(Int) from Int to Int from UInt to UInt { +abstract RGBA(UInt) from Int to Int from UInt to UInt { private static var __alpha16:UInt32Array; diff --git a/lime/system/CFFI.hx b/lime/system/CFFI.hx index dab558d0d..2cfa4d497 100644 --- a/lime/system/CFFI.hx +++ b/lime/system/CFFI.hx @@ -23,7 +23,7 @@ class CFFI { private static function __init__ ():Void { - #if (cpp || neko || nodejs) + #if lime_cffi available = true; enabled = #if disable_cffi false; #else true; #end #else @@ -85,7 +85,7 @@ class CFFI { } else { - #if (iphone || emscripten || android || static_link || tvos) + #if (cpp && (iphone || emscripten || android || static_link || tvos)) return cpp.Lib.load (library, method, args); #end @@ -98,6 +98,8 @@ class CFFI { return neko.Lib.load (__moduleNames.get (library), method, args); #elseif nodejs return untyped __nodeNDLLModule.load_lib (__moduleNames.get (library), method, args); + #elseif cs + return untyped CSFunctionLoader.load (__moduleNames.get (library), method, args); #else return null; #end @@ -327,6 +329,8 @@ class CFFI { var result = neko.Lib.load (name, func, args); #elseif nodejs var result = untyped __nodeNDLLModule.load_lib (name, func, args); + #elseif cs + var result = CSFunctionLoader.load (name, func, args); #else var result = null; #end @@ -355,6 +359,87 @@ class CFFI { } +#if cs +@:dox(hide) private class CSFunctionLoader +{ + public static function load (name:String, func:String, args:Int):Dynamic { + + var func:cs.ndll.NDLLFunction = cs.ndll.NDLLFunction.Load (name, func, args); + + if (func == null) { + + return null; + + } + + if (args == -1) { + + var haxeFunc:Dynamic = function (args:Array):Dynamic { + + return func.CallMult(args); + + } + + return Reflect.makeVarArgs (haxeFunc); + + } else if (args == 0) { + + return function ():Dynamic { + + return func.Call0(); + + } + + } else if (args == 1) { + + return function (arg1:Dynamic):Dynamic { + + return func.Call1(arg1); + + } + + } else if (args == 2) { + + return function (arg1:Dynamic, arg2:Dynamic):Dynamic { + + return func.Call2(arg1, arg2); + + } + + } else if (args == 3) { + + return function (arg1:Dynamic, arg2:Dynamic, arg3:Dynamic):Dynamic { + + return func.Call3(arg1, arg2, arg3); + + } + + } else if (args == 4) { + + return function (arg1:Dynamic, arg2:Dynamic, arg3:Dynamic, arg4:Dynamic):Dynamic { + + return func.Call4(arg1, arg2, arg3, arg4); + + } + + + } else if (args == 5) { + + return function (arg1:Dynamic, arg2:Dynamic, arg3:Dynamic, arg4:Dynamic, arg5:Dynamic):Dynamic { + + return func.Call5(arg1, arg2, arg3, arg4, arg5); + + } + + } + + return null; + + } +} +#end + + #else diff --git a/lime/system/CFFIPointer.hx b/lime/system/CFFIPointer.hx index af4c097a2..a83548fc2 100644 --- a/lime/system/CFFIPointer.hx +++ b/lime/system/CFFIPointer.hx @@ -19,7 +19,7 @@ abstract CFFIPointer(Dynamic) from Dynamic to Dynamic { if (this != null) { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_cffi_get_native_pointer (this); #end @@ -51,7 +51,7 @@ abstract CFFIPointer(Dynamic) from Dynamic to Dynamic { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_cffi_get_native_pointer (ptr:Dynamic):Float; #end diff --git a/lime/system/Clipboard.hx b/lime/system/Clipboard.hx index 152cad4ef..728b31603 100644 --- a/lime/system/Clipboard.hx +++ b/lime/system/Clipboard.hx @@ -25,7 +25,7 @@ class Clipboard { private static function get_text ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_clipboard_get_text (); #elseif flash if (FlashClipboard.generalClipboard.hasFormat (TEXT_FORMAT)) { @@ -42,7 +42,7 @@ class Clipboard { private static function set_text (value:String):String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_clipboard_set_text (value); return value; #elseif flash @@ -62,7 +62,7 @@ class Clipboard { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_clipboard_get_text ():Dynamic; @:cffi private static function lime_clipboard_set_text (text:String):Void; #end diff --git a/lime/system/System.hx b/lime/system/System.hx index 156b47306..e910edfff 100644 --- a/lime/system/System.hx +++ b/lime/system/System.hx @@ -148,7 +148,7 @@ class System { public static function getDisplay (id:Int):Display { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var displayInfo:Dynamic = lime_system_get_display (id); if (displayInfo != null) { @@ -249,7 +249,7 @@ class System { private static function get_allowScreenTimeout ():Bool { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_allow_screen_timeout (); #else return true; @@ -260,7 +260,7 @@ class System { private static function set_allowScreenTimeout (value:Bool):Bool { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_set_allow_screen_timeout (value); #else return true; @@ -271,7 +271,7 @@ class System { private static function get_applicationDirectory ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.APPLICATION, null, null); #elseif flash if (Capabilities.playerType == "Desktop") { @@ -311,7 +311,7 @@ class System { } - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.APPLICATION_STORAGE, company, file); #elseif flash if (Capabilities.playerType == "Desktop") { @@ -332,7 +332,7 @@ class System { private static function get_desktopDirectory ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.DESKTOP, null, null); #elseif flash if (Capabilities.playerType == "Desktop") { @@ -353,7 +353,7 @@ class System { private static function get_documentsDirectory ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.DOCUMENTS, null, null); #elseif flash if (Capabilities.playerType == "Desktop") { @@ -374,7 +374,7 @@ class System { private static function get_fontsDirectory ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.FONTS, null, null); #else return null; @@ -385,7 +385,7 @@ class System { private static function get_numDisplays ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_num_displays (); #else return 1; @@ -396,7 +396,7 @@ class System { private static function get_userDirectory ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_system_get_directory (SystemDirectory.USER, null, null); #elseif flash if (Capabilities.playerType == "Desktop") { @@ -435,7 +435,7 @@ class System { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_system_get_allow_screen_timeout ():Bool; @:cffi private static function lime_system_set_allow_screen_timeout (value:Bool):Bool; @:cffi private static function lime_system_get_directory (type:Int, company:String, title:String):Dynamic; diff --git a/lime/text/Font.hx b/lime/text/Font.hx index 785a38e80..cd56b8d3a 100644 --- a/lime/text/Font.hx +++ b/lime/text/Font.hx @@ -13,7 +13,7 @@ import js.html.CanvasElement; import js.html.CanvasRenderingContext2D; #end -#if ((cpp || neko || nodejs) && !macro) +#if (lime_cffi && !macro) import haxe.io.Path; #end @@ -42,7 +42,7 @@ class Font { public var unitsPerEM (get, null):Int; @:noCompletion private var __fontPath:String; - #if (cpp || neko || nodejs) + #if lime_cffi @:noCompletion private var __fontPathWithoutDirectory:String; #end @@ -66,7 +66,7 @@ class Font { public function decompose ():NativeFontData { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) if (src == null) throw "Uninitialized font handle."; var data:Dynamic = lime_font_outline_decompose (src, 1024 * 20); @@ -88,7 +88,7 @@ class Font { var font = new Font (); font.__fromBytes (bytes); - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return (font.src != null) ? font : null; #else return font; @@ -104,7 +104,7 @@ class Font { var font = new Font (); font.__fromFile (path); - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return (font.src != null) ? font : null; #else return font; @@ -115,7 +115,7 @@ class Font { public function getGlyph (character:String):Glyph { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_glyph_index (src, character); #else return -1; @@ -126,7 +126,7 @@ class Font { public function getGlyphs (characters:String = #if (display && haxe_ver < 3.2) "" #else "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^`'\"/\\&*()[]{}<>|:;_-+=?,. " #end):Array { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var glyphs:Dynamic = lime_font_get_glyph_indices (src, characters); return glyphs; #else @@ -138,7 +138,7 @@ class Font { public function getGlyphMetrics (glyph:Glyph):GlyphMetrics { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var value:Dynamic = lime_font_get_glyph_metrics (src, glyph); var metrics = new GlyphMetrics (); @@ -157,7 +157,7 @@ class Font { public function renderGlyph (glyph:Glyph, fontSize:Int):Image { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) __setSize (fontSize); @@ -195,7 +195,7 @@ class Font { public function renderGlyphs (glyphs:Array, fontSize:Int):Map { - //#if ((cpp || neko || nodejs) && !macro) + //#if (lime_cffi && !macro) // //var uniqueGlyphs = new Map (); // @@ -361,7 +361,7 @@ class Font { __fontPath = null; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) __fontPathWithoutDirectory = null; @@ -382,7 +382,7 @@ class Font { __fontPath = path; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) __fontPathWithoutDirectory = Path.withoutDirectory (__fontPath); @@ -401,7 +401,7 @@ class Font { @:noCompletion private function __setSize (size:Int):Void { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_font_set_size (src, size); #end @@ -417,7 +417,7 @@ class Font { private function get_ascender ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_ascender (src); #else return 0; @@ -428,7 +428,7 @@ class Font { private function get_descender ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_descender (src); #else return 0; @@ -439,7 +439,7 @@ class Font { private function get_height ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_height (src); #else return 0; @@ -450,7 +450,7 @@ class Font { private function get_numGlyphs ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_num_glyphs (src); #else return 0; @@ -461,7 +461,7 @@ class Font { private function get_underlinePosition ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_underline_position (src); #else return 0; @@ -472,7 +472,7 @@ class Font { private function get_underlineThickness ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_underline_thickness (src); #else return 0; @@ -483,7 +483,7 @@ class Font { private function get_unitsPerEM ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_font_get_units_per_em (src); #else return 0; @@ -499,7 +499,7 @@ class Font { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_font_get_ascender (handle:Dynamic):Int; @:cffi private static function lime_font_get_descender (handle:Dynamic):Int; @:cffi private static function lime_font_get_family_name (handle:Dynamic):Dynamic; diff --git a/lime/text/TextLayout.hx b/lime/text/TextLayout.hx index b5b097266..91eda9e08 100644 --- a/lime/text/TextLayout.hx +++ b/lime/text/TextLayout.hx @@ -45,7 +45,7 @@ class TextLayout { positions = []; __dirty = true; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) __handle = lime_text_layout_create (__direction, __script, __language); #end } @@ -55,7 +55,7 @@ class TextLayout { positions = []; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) if (__handle != null && text != null && text != "" && font != null && font.src != null) { @@ -128,7 +128,7 @@ class TextLayout { __direction = value; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_text_layout_set_direction (__handle, value); #end @@ -178,7 +178,7 @@ class TextLayout { __language = value; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_text_layout_set_language (__handle, value); #end @@ -202,7 +202,7 @@ class TextLayout { __script = value; - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_text_layout_set_script (__handle, value); #end @@ -242,7 +242,7 @@ class TextLayout { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_text_layout_create (direction:Int, script:String, language:String):Dynamic; @:cffi private static function lime_text_layout_position (textHandle:Dynamic, fontHandle:Dynamic, size:Int, textString:String, data:Dynamic):Dynamic; @:cffi private static function lime_text_layout_set_direction (textHandle:Dynamic, direction:Int):Void; diff --git a/lime/tools/helpers/CSHelper.hx b/lime/tools/helpers/CSHelper.hx new file mode 100644 index 000000000..cc4dc8a0b --- /dev/null +++ b/lime/tools/helpers/CSHelper.hx @@ -0,0 +1,301 @@ +package lime.tools.helpers; + +import lime.project.Architecture; +import lime.project.HXProject; +import lime.project.NDLL; +import lime.tools.helpers.ProcessHelper; +import sys.io.File; +import sys.FileSystem; +using StringTools; + +class CSHelper { + + public static var ndllSourceFiles:Array = [ + "cs.ndll.NDLLFunction", + "cs.ndll.CFFICSLoader", + "cs.ndll.CSAbstract", + "cs.ndll.CSHandleContainer", + "cs.ndll.CSHandleScope", + "cs.ndll.CSPersistent", + "cs.ndll.DelegateConverter", + "cs.ndll.HandleUtils", + "cs.ndll.NativeMethods", + "cs.ndll.NDLLFunction", + ]; + + private static function getAndroidABIName(arch:Architecture):String { + + var name = switch(arch) { + case ARMV5: + "armeabi"; + case ARMV7: + "armeabi-v7a"; + case ARM64: + "arm64-v8a"; + case X86: + "x86"; + case X64: + "x86_64"; + case _: + null; + } + + if (name == null) { + + throw "Unsupported architecture:" + arch; + + } + + return name; + + } + + public static function getAndroidABINames (architectures:Array):String { + + var result = ""; + var first = true; + + for (arch in architectures) { + + if (first) { + + first = false; + + } else { + + result += ","; + + } + + var archName = getAndroidABIName (arch); + result += archName; + + } + + return result; + + } + + public static function getAndroidNativeLibraryPaths (libPath:String, libraries:Array, architectures:Array):Array { + + var paths = []; + + for (arch in architectures) { + + var archName = getAndroidABIName (arch); + + for (lib in libraries) { + + paths.push (FileSystem.absolutePath (libPath + "/" + archName + "/" + "lib" + lib.name + ".so").replace ("/", "\\")); + + } + + } + + return paths; + + } + + public static function copySourceFiles (templatePaths:Array, targetPath:String) { + + FileHelper.recursiveCopyTemplate (templatePaths, "cs/src", targetPath); + + } + + public static function addSourceFiles (txtPath:String, sourceFiles:Array) { + + if (sourceFiles.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin modules\n'); + + for (fileName in sourceFiles) { + + file.writeString ('M $fileName\nC $fileName\n'); + + } + + file.writeString ('end modules\n'); + file.close(); + + } + + public static function addAndroidResources (txtPath:String, resources:Array) { + + if (resources.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin android_resources\n'); + + for (resource in resources) { + + file.writeString ('$resource\n'); + + } + + file.writeString ('end android_resources\n'); + file.close(); + + } + + public static function addAssemblies (txtPath:String, assemblies:Array) { + + if (assemblies.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin libs\n'); + + for (assembly in assemblies) { + + file.writeString (assembly.replace("/", "\\") + '\n'); + + } + + file.writeString ('end libs\n'); + file.close(); + + } + + public static function addNativeLibraries (txtPath:String, libPath:String, libraries:Array, architectures:Array) { + + if (libraries.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin native_libs\n'); + + for (arch in architectures) { + + var archName = getAndroidABIName (arch); + + for (lib in libraries) { + + file.writeString (FileSystem.absolutePath(libPath + "/" + archName + "/" + "lib" + lib.name + ".so").replace("/", "\\") + '\n'); + + } + + } + + file.writeString ('end native_libs\n'); + file.close(); + + } + + public static function addAndroidABIs (txtPath:String, architectures:Array) { + + if (architectures.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin android_abis\n'); + + for (arch in architectures) { + + var archName = getAndroidABIName (arch); + file.writeString (archName + '\n'); + + } + + file.writeString ('end android_abis\n'); + file.close(); + + } + + + public static function addAssets (txtPath:String, assets:Array) { + + if (assets.length == 0) { + + return; + + } + + var file = File.append (txtPath, false); + file.writeString ('\nbegin android_assets\n'); + + for (asset in assets) { + + file.writeString (FileSystem.absolutePath(asset).replace("/", "\\") + '\n'); + + } + + file.writeString ('end android_assets\n'); + file.close(); + + } + + public static function addGUID (txtPath:String, guid:String) { + + var file = File.append (txtPath, false); + file.writeString ('\nbegin guid\n'); + + file.writeString ('$guid\n'); + + file.writeString ('end guid\n'); + file.close (); + + } + + public static function compile (project:HXProject, path:String, outPath:String, arch:String, platform:String, buildFile:String = "hxcs_build.txt", noCompile:Bool = false) { + + var args = [ "run", project.config.getString ("cs.buildLibrary", "hxcs"), buildFile, "--arch", arch, "--platform", platform, "--out", outPath, "--unsafe" ]; + if (noCompile) + args.push ("--no-compile"); + var code = ProcessHelper.runCommand (path, "haxelib", args); + + if (code != 0) { + + Sys.exit (code); + + } + + } + + public static function buildGradleProj (path:String) { + + var gradlePath = FileSystem.absolutePath(path + "/" + "gradlew"); + ProcessHelper.runCommand (path, gradlePath, ["build", "assembleRelease"]); + + } + + inline public static function buildSln (path:String, slnPath:String, task:String = null) { + + buildCSProj (path, slnPath, task); + + } + + public static function buildCSProj (path:String, csprojPath:String, task:String = null) { + + var msBuildPath = "C:/Program Files (x86)/MSBuild/14.0/Bin/MSBuild.exe"; + var absCSProjPath = FileSystem.absolutePath(csprojPath); + var args = [absCSProjPath, "/p:Configuration=Release"]; + + if (task != null) { + + args.push ("/t:" + task); + + } + + ProcessHelper.runCommand (path, msBuildPath, args); + + } + +} diff --git a/lime/tools/helpers/GUID.hx b/lime/tools/helpers/GUID.hx new file mode 100644 index 000000000..76e903bb5 --- /dev/null +++ b/lime/tools/helpers/GUID.hx @@ -0,0 +1,41 @@ +package lime.tools.helpers; + +// https://groups.google.com/d/msg/haxelang/N03kf5WSrTU/KU8nmsaqfIIJ +class GUID { + + inline public static function randomIntegerWithinRange (min:Int, max:Int):Int { + + return Math.floor(Math.random() * (1 + max - min) + min); + + } + + public static function createRandomIdentifier (length:Int, radix:Int = 61):String { + + var characters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']; + var id:Array = new Array (); + radix = (radix > 61) ? 61 : radix; + + while (length-- > 0) { + + id.push (characters[GUID.randomIntegerWithinRange (0, radix)]); + } + + return id.join(''); + } + + public static function uuid ():String { + + var specialChars = ['8', '9', 'A', 'B']; + + + return "{" + GUID.createRandomIdentifier (8, 15) + '-' + + GUID.createRandomIdentifier (4, 15) + '-4' + + GUID.createRandomIdentifier (3, 15) + '-' + + specialChars[GUID.randomIntegerWithinRange (0, 3)] + + GUID.createRandomIdentifier (3, 15) + '-' + + GUID.createRandomIdentifier (12, 15) + + "}"; + + } + +} \ No newline at end of file diff --git a/lime/tools/helpers/LogHelper.hx b/lime/tools/helpers/LogHelper.hx index d1884dca6..d81552f89 100644 --- a/lime/tools/helpers/LogHelper.hx +++ b/lime/tools/helpers/LogHelper.hx @@ -10,6 +10,8 @@ import sys.io.Process; import neko.Lib; #elseif cpp import cpp.Lib; +#elseif cs +import cs.Lib; #end diff --git a/lime/tools/platforms/WindowsPlatform.hx b/lime/tools/platforms/WindowsPlatform.hx index 57e99fd09..41acafea3 100644 --- a/lime/tools/platforms/WindowsPlatform.hx +++ b/lime/tools/platforms/WindowsPlatform.hx @@ -10,6 +10,8 @@ import lime.tools.helpers.DeploymentHelper; import lime.tools.helpers.FileHelper; import lime.tools.helpers.IconHelper; import lime.tools.helpers.LogHelper; +import lime.tools.helpers.CSHelper; +import lime.tools.helpers.GUID; import lime.tools.helpers.NekoHelper; import lime.tools.helpers.NodeJSHelper; import lime.tools.helpers.PathHelper; @@ -42,9 +44,13 @@ class WindowsPlatform extends PlatformTarget { targetType = "neko"; } else if (project.targetFlags.exists ("nodejs")) { - + targetType = "nodejs"; + } else if (project.targetFlags.exists ("cs")) { + + targetType = "cs"; + } else { targetType = "cpp"; @@ -116,6 +122,15 @@ class WindowsPlatform extends PlatformTarget { //NekoHelper.createExecutable (project.templatePaths, "windows", targetDirectory + "/obj/ApplicationMain.n", executablePath); NekoHelper.copyLibraries (project.templatePaths, "windows", applicationDirectory); + } else if (targetType == "cs") { + + ProcessHelper.runCommand ("", "haxe", [ hxml ]); + CSHelper.copySourceFiles (project.templatePaths, targetDirectory + "/obj/src"); + var txtPath = targetDirectory + "/obj/hxcs_build.txt"; + CSHelper.addSourceFiles (txtPath, CSHelper.ndllSourceFiles); + CSHelper.addGUID (txtPath, GUID.uuid ()); + CSHelper.compile (project, targetDirectory + "/obj", applicationDirectory + project.app.file, "x86", "desktop"); + } else { var haxeArgs = [ hxml ]; diff --git a/lime/ui/FileDialog.hx b/lime/ui/FileDialog.hx index 84ad703b5..6d57bd58c 100644 --- a/lime/ui/FileDialog.hx +++ b/lime/ui/FileDialog.hx @@ -308,7 +308,7 @@ class FileDialog { - #if (cpp || neko || nodejs) + #if lime_cffi @:cffi private static function lime_file_dialog_open_directory (filter:String, defaultPath:String):Dynamic; @:cffi private static function lime_file_dialog_open_file (filter:String, defaultPath:String):Dynamic; @:cffi private static function lime_file_dialog_open_files (filter:String, defaultPath:String):Dynamic; diff --git a/lime/ui/Gamepad.hx b/lime/ui/Gamepad.hx index dde857c1f..dabd2a048 100644 --- a/lime/ui/Gamepad.hx +++ b/lime/ui/Gamepad.hx @@ -36,7 +36,7 @@ class Gamepad { public static function addMappings (mappings:Array):Void { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) lime_gamepad_add_mappings (mappings); #end @@ -75,7 +75,7 @@ class Gamepad { @:noCompletion private inline function get_guid ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_gamepad_get_device_guid (this.id); #elseif (js && html5) var devices = Joystick.__getDeviceData (); @@ -89,7 +89,7 @@ class Gamepad { @:noCompletion private inline function get_name ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_gamepad_get_device_name (this.id); #elseif (js && html5) var devices = Joystick.__getDeviceData (); @@ -108,7 +108,7 @@ class Gamepad { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_gamepad_add_mappings (mappings:Dynamic):Void; @:cffi private static function lime_gamepad_get_device_guid (id:Int):Dynamic; @:cffi private static function lime_gamepad_get_device_name (id:Int):Dynamic; diff --git a/lime/ui/Joystick.hx b/lime/ui/Joystick.hx index 3df4f07be..a17706de6 100644 --- a/lime/ui/Joystick.hx +++ b/lime/ui/Joystick.hx @@ -79,7 +79,7 @@ class Joystick { @:noCompletion private inline function get_guid ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_device_guid (this.id); #elseif (js && html5) var devices = __getDeviceData (); @@ -93,7 +93,7 @@ class Joystick { @:noCompletion private inline function get_name ():String { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_device_name (this.id); #elseif (js && html5) var devices = __getDeviceData (); @@ -107,7 +107,7 @@ class Joystick { @:noCompletion private inline function get_numAxes ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_num_axes (this.id); #elseif (js && html5) var devices = __getDeviceData (); @@ -121,7 +121,7 @@ class Joystick { @:noCompletion private inline function get_numButtons ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_num_buttons (this.id); #elseif (js && html5) var devices = __getDeviceData (); @@ -135,7 +135,7 @@ class Joystick { @:noCompletion private inline function get_numHats ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_num_hats (this.id); #else return 0; @@ -146,7 +146,7 @@ class Joystick { @:noCompletion private inline function get_numTrackballs ():Int { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) return lime_joystick_get_num_trackballs (this.id); #else return 0; @@ -162,7 +162,7 @@ class Joystick { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_joystick_get_device_guid (id:Int):Dynamic; @:cffi private static function lime_joystick_get_device_name (id:Int):Dynamic; @:cffi private static function lime_joystick_get_num_axes (id:Int):Int; diff --git a/lime/utils/Bytes.hx b/lime/utils/Bytes.hx index 012941a53..b583a9833 100644 --- a/lime/utils/Bytes.hx +++ b/lime/utils/Bytes.hx @@ -67,7 +67,7 @@ class Bytes extends HaxeBytes { } - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) public static function __fromNativePointer (data:Dynamic, length:Int):Bytes { var bytes:Dynamic = lime_bytes_from_data_pointer (data, length); diff --git a/lime/utils/Int8Array.hx b/lime/utils/Int8Array.hx index d96f31ebc..ae5443e61 100644 --- a/lime/utils/Int8Array.hx +++ b/lime/utils/Int8Array.hx @@ -94,9 +94,9 @@ package lime.utils; //non spec haxe conversions inline public static function fromBytes( bytes:haxe.io.Bytes, ?byteOffset:Int=0, ?len:Int ) : Int8Array { - if(byteOffset == null) return new Int8Array(cast bytes.getData()); - if(len == null) return new Int8Array(cast bytes.getData(), byteOffset); - return new Int8Array(cast bytes.getData(), byteOffset, len); + if(byteOffset == null) return new Int8Array(null, null, cast bytes.getData()); + if(len == null) return new Int8Array(null, null, cast bytes.getData(), byteOffset); + return new Int8Array(null, null, cast bytes.getData(), byteOffset, len); } inline public function toBytes() : haxe.io.Bytes { diff --git a/lime/utils/compress/Deflate.hx b/lime/utils/compress/Deflate.hx index 2aa4a836c..ce35a90f0 100644 --- a/lime/utils/compress/Deflate.hx +++ b/lime/utils/compress/Deflate.hx @@ -17,7 +17,7 @@ class Deflate { public static function compress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_deflate_compress (bytes); if (data == null) return null; @@ -49,7 +49,7 @@ class Deflate { public static function decompress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_deflate_decompress (bytes); if (data == null) return null; @@ -86,7 +86,7 @@ class Deflate { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_deflate_compress (data:Dynamic):Dynamic; @:cffi private static function lime_deflate_decompress (data:Dynamic):Dynamic; #end diff --git a/lime/utils/compress/GZip.hx b/lime/utils/compress/GZip.hx index 570f1bb91..9687c812e 100644 --- a/lime/utils/compress/GZip.hx +++ b/lime/utils/compress/GZip.hx @@ -13,7 +13,7 @@ class GZip { public static function compress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_gzip_compress (bytes); if (data == null) return null; @@ -35,7 +35,7 @@ class GZip { public static function decompress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_gzip_decompress (bytes); if (data == null) return null; @@ -62,7 +62,7 @@ class GZip { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_gzip_compress (data:Dynamic):Dynamic; @:cffi private static function lime_gzip_decompress (data:Dynamic):Dynamic; #end diff --git a/lime/utils/compress/LZMA.hx b/lime/utils/compress/LZMA.hx index 9d24cb09b..fc02486ea 100644 --- a/lime/utils/compress/LZMA.hx +++ b/lime/utils/compress/LZMA.hx @@ -18,7 +18,7 @@ class LZMA { public static function compress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_lzma_compress (bytes); if (data == null) return null; @@ -45,7 +45,7 @@ class LZMA { public static function decompress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_lzma_decompress (bytes); if (data == null) return null; @@ -77,7 +77,7 @@ class LZMA { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_lzma_compress (data:Dynamic):Dynamic; @:cffi private static function lime_lzma_decompress (data:Dynamic):Dynamic; #end diff --git a/lime/utils/compress/Zlib.hx b/lime/utils/compress/Zlib.hx index f3bcaf180..9340f055f 100644 --- a/lime/utils/compress/Zlib.hx +++ b/lime/utils/compress/Zlib.hx @@ -17,7 +17,7 @@ class Zlib { public static function compress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_zlib_compress (bytes); if (data == null) return null; @@ -49,7 +49,7 @@ class Zlib { public static function decompress (bytes:Bytes):Bytes { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) var data:Dynamic = lime_zlib_decompress (bytes); if (data == null) return null; @@ -86,7 +86,7 @@ class Zlib { - #if ((cpp || neko || nodejs) && !macro) + #if (lime_cffi && !macro) @:cffi private static function lime_zlib_compress (data:Dynamic):Dynamic; @:cffi private static function lime_zlib_decompress (data:Dynamic):Dynamic; #end diff --git a/templates/cs/hxml/debug.hxml b/templates/cs/hxml/debug.hxml new file mode 100644 index 000000000..c71d56b22 --- /dev/null +++ b/templates/cs/hxml/debug.hxml @@ -0,0 +1,6 @@ +-main ApplicationMain ::HAXE_FLAGS:: +-D net-ver=40 +-cp ::OUTPUT_DIR::/haxe +-cs ::OUTPUT_DIR::/obj +--macro keep("::APP_MAIN::") +-debug \ No newline at end of file diff --git a/templates/cs/hxml/final.hxml b/templates/cs/hxml/final.hxml new file mode 100644 index 000000000..914dc1efe --- /dev/null +++ b/templates/cs/hxml/final.hxml @@ -0,0 +1,7 @@ +-main ApplicationMain ::HAXE_FLAGS:: +-D net-ver=40 +-D real-position +-cp ::OUTPUT_DIR::/haxe +-cs ::OUTPUT_DIR::/obj +--macro keep("::APP_MAIN::") +-D final \ No newline at end of file diff --git a/templates/cs/hxml/release.hxml b/templates/cs/hxml/release.hxml new file mode 100644 index 000000000..b2f464ee6 --- /dev/null +++ b/templates/cs/hxml/release.hxml @@ -0,0 +1,6 @@ +-main ApplicationMain ::HAXE_FLAGS:: +-D net-ver=40 +-D real-position +-cp ::OUTPUT_DIR::/haxe +-cs ::OUTPUT_DIR::/obj +--macro keep("::APP_MAIN::") \ No newline at end of file diff --git a/templates/cs/src/cs/ndll/CFFICSLoader.cs b/templates/cs/src/cs/ndll/CFFICSLoader.cs new file mode 100644 index 000000000..00648ca80 --- /dev/null +++ b/templates/cs/src/cs/ndll/CFFICSLoader.cs @@ -0,0 +1,792 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using haxe.lang; + +namespace cs.ndll +{ + class CFFICSLoader + { + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate IntPtr CFFILoaderDelegate(String inName); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int ValTypeDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int AllocKindDelegate(); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocAbstractDelegate(int arg1, IntPtr arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void FreeAbstractDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValToKindDelegate(IntPtr arg1, int arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValDataDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValArrayIntDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocBoolDelegate([MarshalAs(UnmanagedType.I1)]bool arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocNullDelegate(); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr CreateRootDelegate(IntPtr inValue); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr QueryRootDelegate(IntPtr inValue); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void DestroyRootDelegate(IntPtr inValue); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void ValGCDelegate(IntPtr arg1, CSAbstract.FinalizerDelegate arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate double ValNumberDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int ValStrLenDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValStringDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int ValIntDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocIntDelegate(int arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocArrayDelegate(int arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocArrayTypeDelegate(int arg1, hxValueType arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int ValArraySizeDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValArrayIDelegate(IntPtr arg1, int arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void ValArraySetIDelegate(IntPtr arg1, int arg2, IntPtr arg3); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void ValArrayPushDelegate(IntPtr arg1, IntPtr arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int ValIdDelegate(String arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void AllocFieldDelegate(IntPtr arg1, int arg2, IntPtr arg3); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValCall0Delegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocEmptyObjectDelegate(); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocStringLenDelegate(IntPtr inStr, int inLen); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocWStringLenDelegate(IntPtr inStr, int inLen); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocFloatDelegate(double arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr AllocBufferLenDelegate(int inLen); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr BufferDataDelegate(IntPtr inBuffer); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr BufferValDelegate(IntPtr b); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValToBufferDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate int BufferSizeDelegate(IntPtr inBuffer); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr PinBufferDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void UnPinBufferDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr ValFieldDelegate(IntPtr arg1, int arg2); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate bool ValBoolDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void ValThrowDelegate(IntPtr arg1); + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr EmptyDelegate(); + + private enum hxValueType + { + valtUnknown = -1, + valtInt = 0xff, + valtNull = 0, + valtFloat = 1, + valtBool = 2, + valtString = 3, + valtObject = 4, + valtArray = 5, + valtFunction = 6, + valtEnum, + valtClass, + valtRoot = 0xff, + valtAbstractBase = 0x100, + }; + + private static int sgKinds = (int)(hxValueType.valtAbstractBase + 2); + + private static DelegateConverter val_type; + private static DelegateConverter alloc_kind; + private static DelegateConverter alloc_abstract; + private static DelegateConverter free_abstract; + private static DelegateConverter val_to_kind; + private static DelegateConverter val_data; + private static DelegateConverter val_array_int; + private static DelegateConverter alloc_bool; + private static DelegateConverter alloc_null; + private static DelegateConverter create_root; + private static DelegateConverter query_root; + private static DelegateConverter destroy_root; + private static DelegateConverter val_gc; + private static DelegateConverter val_number; + private static DelegateConverter val_strlen; + private static DelegateConverter val_string; + private static DelegateConverter val_int; + private static DelegateConverter alloc_int; + private static DelegateConverter alloc_array; + private static DelegateConverter alloc_array_type; + private static DelegateConverter val_array_size; + private static DelegateConverter val_array_i; + private static DelegateConverter val_array_set_i; + private static DelegateConverter val_array_push; + private static DelegateConverter val_id; + private static DelegateConverter alloc_field; + private static DelegateConverter val_call0; + private static DelegateConverter alloc_empty_object; + private static DelegateConverter alloc_string_len; + private static DelegateConverter alloc_wstring_len; + private static DelegateConverter alloc_float; + private static DelegateConverter alloc_buffer_len; + private static DelegateConverter buffer_data; + private static DelegateConverter buffer_val; + private static DelegateConverter val_to_buffer; + private static DelegateConverter buffer_size; + private static DelegateConverter pin_buffer; + private static DelegateConverter unpin_buffer; + private static DelegateConverter val_field; + private static DelegateConverter val_bool; + private static DelegateConverter val_throw; + private static DelegateConverter empty; + + private static int cs_val_type(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return (int)hxValueType.valtNull; + + if (arg1 is Boolean) + return (int)hxValueType.valtBool; + else if (arg1 is sbyte || + arg1 is byte || + arg1 is short || + arg1 is ushort || + arg1 is int || + arg1 is uint || + arg1 is long || + arg1 is ulong) + return (int)hxValueType.valtInt; + else if (arg1 is float || + arg1 is double || + arg1 is decimal) + return (int)hxValueType.valtFloat; + else if (arg1 is String) + return (int)hxValueType.valtString; + else if (arg1 is Array) + return (int)hxValueType.valtArray; + else if (arg1 is Function) + return (int)hxValueType.valtFunction; + else if (arg1.GetType().IsEnum) + return (int)hxValueType.valtEnum; + else if (arg1.GetType().IsClass) + return (int)hxValueType.valtClass; + else if (arg1 is DynamicObject) + return (int)hxValueType.valtObject; + else if (arg1 is CSAbstract) + return ((CSAbstract)arg1).Kind; + + return (int)hxValueType.valtUnknown; + } + + // Abstract types + private static int cs_alloc_kind() + { + return ++sgKinds; + } + + private static IntPtr cs_alloc_abstract(int arg1, IntPtr arg2) + { + return CSHandleContainer.GetCurrent().CreateGCHandle(new CSAbstract(arg1, arg2)); + } + + private static void cs_free_abstract(IntPtr inArg1) + { + CSAbstract arg1 = (CSAbstract)HandleUtils.GetObjectFromIntPtr(inArg1); + arg1.Free(); + } + + private static IntPtr cs_val_to_kind(IntPtr inArg1, int arg2) + { + CSAbstract arg1 = (CSAbstract)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return IntPtr.Zero; + + return arg1.Kind == arg2 ? arg1.Pointer : IntPtr.Zero; + } + + private static IntPtr cs_val_data(IntPtr inArg1) + { + CSAbstract arg1 = (CSAbstract)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return IntPtr.Zero; + + return arg1.Pointer; + } + + private static IntPtr cs_val_array_int(IntPtr inArg1) + { + Array arg1 = (Array)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return IntPtr.Zero; + + Array intHxArray = arg1 as Array; + if (intHxArray != null) + return CSHandleContainer.GetCurrent().GetAddrOfBlittableObject(intHxArray.__a); + + return IntPtr.Zero; + } + + private static IntPtr cs_alloc_bool(bool arg1) + { + return CSHandleContainer.GetCurrent().CreateGCHandle(arg1); + } + + private static IntPtr cs_alloc_null() + { + return IntPtr.Zero; + } + + private static IntPtr cs_create_root(IntPtr inValue) + { + object value = HandleUtils.GetObjectFromIntPtr(inValue); + GCHandle handle = GCHandle.Alloc(new CSPersistent(value)); + return GCHandle.ToIntPtr(handle); + } + + private static IntPtr cs_query_root(IntPtr inValue) + { + CSPersistent persistent = (CSPersistent)HandleUtils.GetObjectFromIntPtr(inValue); + return CSHandleContainer.GetCurrent().CreateGCHandle(persistent.Value); + } + + private static void cs_destroy_root(IntPtr inValue) + { + GCHandle handle = GCHandle.FromIntPtr(inValue); + CSPersistent persistent = (CSPersistent)handle.Target; + handle.Free(); + } + + private static void cs_val_gc(IntPtr inArg1, CSAbstract.FinalizerDelegate arg2) + { + CSAbstract arg1 = (CSAbstract)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return; + + arg1.Finalizer = arg2; + } + + private static double cs_val_number(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return 0; + + if (arg1 is sbyte) + return (sbyte)arg1; + else if (arg1 is byte) + return (byte)arg1; + else if (arg1 is short) + return (short)arg1; + else if (arg1 is ushort) + return (ushort)arg1; + else if (arg1 is int) + return (int)arg1; + else if (arg1 is uint) + return (uint)arg1; + else if (arg1 is long) + return (long)arg1; + else if (arg1 is ulong) + return (ulong)arg1; + else if (arg1 is float) + return (float)arg1; + else if (arg1 is double) + return (double)arg1; + else if (arg1 is decimal) + { + decimal d = (decimal)(arg1); + return decimal.ToDouble(d); + } + + return 0; + } + + private static int cs_val_strlen(IntPtr inArg1) + { + String arg1 = (String)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return 0; + + return Encoding.UTF8.GetByteCount(arg1); + } + + private static IntPtr cs_val_string(IntPtr inArg1) + { + String arg1 = (String)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return IntPtr.Zero; + + CSHandleContainer container = CSHandleContainer.GetCurrent(); + byte[] bytes = System.Text.Encoding.UTF8.GetBytes(arg1); + IntPtr memory = container.AllocateMemory(sizeof(byte) * (bytes.Length + 1)); + Marshal.Copy(bytes, 0, memory, bytes.Length); + Marshal.WriteByte(memory, bytes.Length, 0); + return memory; + } + + private static int cs_val_int(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return 0; + + if (arg1 is sbyte) + return (sbyte)arg1; + else if (arg1 is byte) + return (byte)arg1; + else if (arg1 is short) + return (short)arg1; + else if (arg1 is ushort) + return (ushort)arg1; + else if (arg1 is int) + return (int)arg1; + else if (arg1 is uint) + return (int)(uint)arg1; + else if (arg1 is long) + return (int)(long)arg1; + else if (arg1 is ulong) + return (int)(ulong)arg1; + else if (arg1 is float) + return (int)(float)arg1; + else if (arg1 is double) + return (int)(double)arg1; + else if (arg1 is decimal) + { + decimal d = (decimal)arg1; + return decimal.ToInt32(d); + } + + return 0; + } + + private static IntPtr cs_alloc_int(int arg1) + { + return CSHandleContainer.GetCurrent().CreateGCHandle(arg1); + } + + private static IntPtr cs_alloc_array(int arg1) + { + return CSHandleContainer.GetCurrent().CreateGCHandle(new Array(new object[arg1])); + } + + private static IntPtr cs_alloc_array_type(int arg1, hxValueType arg2) + { + Array arr; + switch(arg2) + { + case hxValueType.valtBool: + arr = new Array(new bool[arg1]); + break; + case hxValueType.valtInt: + arr = new Array(new int[arg1]); + break; + case hxValueType.valtFloat: + arr = new Array(new double[arg1]); + break; + case hxValueType.valtString: + arr = new Array(new String[arg1]); + break; + case hxValueType.valtObject: + arr = new Array(new object[arg1]); + break; + default: + return IntPtr.Zero; + } + return CSHandleContainer.GetCurrent().CreateGCHandle(arr); + } + + private static int cs_val_array_size(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + else if (arg1 is Array) + return ((Array)arg1).length; + + return 0; + } + + private static IntPtr cs_val_array_i(IntPtr inArg1, int arg2) + { + Array arg1 = (Array)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return IntPtr.Zero; + + return CSHandleContainer.GetCurrent().CreateGCHandle(arg1[arg2]); + } + + private static void cs_val_array_set_i(IntPtr inArg1, int arg2, IntPtr inArg3) + { + Array arg1 = (Array)HandleUtils.GetObjectFromIntPtr(inArg1); + object arg3 = HandleUtils.GetObjectFromIntPtr(inArg3); + if (arg1 == null) + return; + + arg1[arg2] = arg3; + } + + private static void cs_val_array_push(IntPtr inArg1, IntPtr inArg2) + { + Array arg1 = (Array)HandleUtils.GetObjectFromIntPtr(inArg1); + object arg2 = HandleUtils.GetObjectFromIntPtr(inArg2); + if (arg1 == null) + return; + + arg1.push(arg2); + } + + private static int cs_val_id(String arg1) + { + return CSHandleContainer.GetCurrent().GetId(arg1); + } + + private static void cs_alloc_field(IntPtr inArg1, int arg2, IntPtr inArg3) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + object arg3 = HandleUtils.GetObjectFromIntPtr(inArg3); + if (arg1 == null) + throw new ArgumentNullException("Null object set"); + + String field = CSHandleContainer.GetCurrent().GetStringFromId(arg2); + Reflect.setField(arg1, field, arg3); + } + + private static IntPtr cs_val_field(IntPtr inArg1, int arg2) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + throw new ArgumentNullException("Null object get"); + + CSHandleContainer container = CSHandleContainer.GetCurrent(); + String field = container.GetStringFromId(arg2); + return container.CreateGCHandle(Reflect.field(arg1, field)); + } + + private static IntPtr cs_val_call0(IntPtr inArg1) + { + Function arg1 = (Function)HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + throw new ArgumentNullException("Null function call"); + + return CSHandleContainer.GetCurrent().CreateGCHandle(arg1.__hx_invoke0_o()); + } + + private static IntPtr cs_alloc_empty_object() + { + return CSHandleContainer.GetCurrent().CreateGCHandle(new DynamicObject()); + } + + private static IntPtr cs_alloc_string_len(IntPtr inStr, int inLen) + { + byte[] bytes = new byte[inLen]; + Marshal.Copy(inStr, bytes, 0, inLen); + String str = Encoding.UTF8.GetString(bytes, 0, inLen); + return CSHandleContainer.GetCurrent().CreateGCHandle(str); + } + + private static IntPtr cs_alloc_wstring_len(IntPtr inStr, int inLen) + { + byte[] bytes; + String str; + int totalLen; + switch(Environment.OSVersion.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + totalLen = inLen * 2; + bytes = new byte[totalLen]; + Marshal.Copy(inStr, bytes, 0, totalLen); + str = Encoding.Unicode.GetString(bytes); + return CSHandleContainer.GetCurrent().CreateGCHandle(str); + default: + totalLen = inLen * 4; + bytes = new byte[totalLen]; + Marshal.Copy(inStr, bytes, 0, totalLen); + str = Encoding.UTF32.GetString(bytes); + return CSHandleContainer.GetCurrent().CreateGCHandle(str); + } + } + + private static IntPtr cs_alloc_float(double arg1) + { + return CSHandleContainer.GetCurrent().CreateGCHandle(arg1); + } + + private static IntPtr cs_alloc_buffer_len(int inLen) + { + byte[] buffer = new byte[inLen]; + return CSHandleContainer.GetCurrent().CreatePinnedGCHandle(buffer); + } + + private static IntPtr cs_buffer_val(IntPtr b) + { + return b; + } + + private static IntPtr cs_val_to_buffer(IntPtr arg1) + { + return arg1; + } + + private static int cs_buffer_size(IntPtr inBuffer) + { + byte[] buffer = (byte[])HandleUtils.GetObjectFromIntPtr(inBuffer); + if (buffer == null) + return 0; + + return buffer.Length; + } + + private static IntPtr cs_buffer_data(IntPtr inBuffer) + { + byte[] buffer = (byte[])HandleUtils.GetObjectFromIntPtr(inBuffer); + if (buffer == null) + return IntPtr.Zero; + + return CSHandleContainer.GetCurrent().GetAddrOfBlittableObject(buffer); + } + + private static IntPtr cs_pin_buffer(IntPtr inBuffer) + { + byte[] buffer = (byte[])GCHandle.FromIntPtr(inBuffer).Target; + return GCHandle.ToIntPtr(GCHandle.Alloc(buffer, GCHandleType.Pinned)); + } + + private static void cs_unpin_buffer(IntPtr inArg1) + { + GCHandle handle = GCHandle.FromIntPtr(inArg1); + handle.Free(); + } + + private static bool cs_val_bool(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + if (arg1 == null) + return false; + + return (bool)arg1; + } + + private static void cs_val_throw(IntPtr inArg1) + { + object arg1 = HandleUtils.GetObjectFromIntPtr(inArg1); + throw new Exception(arg1.ToString()); + } + + private static IntPtr cs_empty() { return IntPtr.Zero; } + + static CFFICSLoader() + { + val_type = new DelegateConverter(new ValTypeDelegate(cs_val_type)); + alloc_kind = new DelegateConverter(new AllocKindDelegate(cs_alloc_kind)); + alloc_abstract = new DelegateConverter(new AllocAbstractDelegate(cs_alloc_abstract)); + free_abstract = new DelegateConverter(new FreeAbstractDelegate(cs_free_abstract)); + val_to_kind = new DelegateConverter(new ValToKindDelegate(cs_val_to_kind)); + val_data = new DelegateConverter(new ValDataDelegate(cs_val_data)); + val_array_int = new DelegateConverter(new ValArrayIntDelegate(cs_val_array_int)); + alloc_bool = new DelegateConverter(new AllocBoolDelegate(cs_alloc_bool)); + alloc_null = new DelegateConverter(new AllocNullDelegate(cs_alloc_null)); + create_root = new DelegateConverter(new CreateRootDelegate(cs_create_root)); + query_root = new DelegateConverter(new QueryRootDelegate(cs_query_root)); + destroy_root = new DelegateConverter(new DestroyRootDelegate(cs_destroy_root)); + val_gc = new DelegateConverter(new ValGCDelegate(cs_val_gc)); + val_number = new DelegateConverter(new ValNumberDelegate(cs_val_number)); + val_strlen = new DelegateConverter(new ValStrLenDelegate(cs_val_strlen)); + val_string = new DelegateConverter(new ValStringDelegate(cs_val_string)); + val_int = new DelegateConverter(new ValIntDelegate(cs_val_int)); + alloc_int = new DelegateConverter(new AllocIntDelegate(cs_alloc_int)); + alloc_array = new DelegateConverter(new AllocArrayDelegate(cs_alloc_array)); + alloc_array_type = new DelegateConverter(new AllocArrayTypeDelegate(cs_alloc_array_type)); + val_array_size = new DelegateConverter(new ValArraySizeDelegate(cs_val_array_size)); + val_array_i = new DelegateConverter(new ValArrayIDelegate(cs_val_array_i)); + val_array_set_i = new DelegateConverter(new ValArraySetIDelegate(cs_val_array_set_i)); + val_array_push = new DelegateConverter(new ValArrayPushDelegate(cs_val_array_push)); + val_id = new DelegateConverter(new ValIdDelegate(cs_val_id)); + alloc_field = new DelegateConverter(new AllocFieldDelegate(cs_alloc_field)); + val_call0 = new DelegateConverter(new ValCall0Delegate(cs_val_call0)); + alloc_empty_object = new DelegateConverter(new AllocEmptyObjectDelegate(cs_alloc_empty_object)); + alloc_string_len = new DelegateConverter(new AllocStringLenDelegate(cs_alloc_string_len)); + alloc_wstring_len = new DelegateConverter(new AllocWStringLenDelegate(cs_alloc_wstring_len)); + alloc_float = new DelegateConverter(new AllocFloatDelegate(cs_alloc_float)); + alloc_buffer_len = new DelegateConverter(new AllocBufferLenDelegate(cs_alloc_buffer_len)); + buffer_data = new DelegateConverter(new BufferDataDelegate(cs_buffer_data)); + buffer_val = new DelegateConverter(new BufferValDelegate(cs_buffer_val)); + val_to_buffer = new DelegateConverter(new ValToBufferDelegate(cs_val_to_buffer)); + buffer_size = new DelegateConverter(new BufferSizeDelegate(cs_buffer_size)); + pin_buffer = new DelegateConverter(new PinBufferDelegate(cs_pin_buffer)); + unpin_buffer = new DelegateConverter(new UnPinBufferDelegate(cs_unpin_buffer)); + val_field = new DelegateConverter(new ValFieldDelegate(cs_val_field)); + val_bool = new DelegateConverter(new ValBoolDelegate(cs_val_bool)); + val_throw = new DelegateConverter(new ValThrowDelegate(cs_val_throw)); + empty = new DelegateConverter(new EmptyDelegate(cs_empty)); + } + + internal static IntPtr Load(String inName) + { + switch (inName) + { + case "val_type": + return val_type.ToPointer(); + case "alloc_kind": + return alloc_kind.ToPointer(); + case "alloc_abstract": + return alloc_abstract.ToPointer(); + case "free_abstract": + return free_abstract.ToPointer(); + case "val_to_kind": + return val_to_kind.ToPointer(); + case "val_array_int": + return val_array_int.ToPointer(); + case "alloc_bool": + return alloc_bool.ToPointer(); + case "alloc_null": + return alloc_null.ToPointer(); + case "create_root": + return create_root.ToPointer(); + case "query_root": + return query_root.ToPointer(); + case "destroy_root": + return destroy_root.ToPointer(); + case "val_data": + return val_data.ToPointer(); + case "alloc_root": + return empty.ToPointer(); + case "val_gc": + return val_gc.ToPointer(); + case "val_number": + return val_number.ToPointer(); + case "val_strlen": + return val_strlen.ToPointer(); + case "val_string": + return val_string.ToPointer(); + case "val_int": + return val_int.ToPointer(); + case "alloc_int": + return alloc_int.ToPointer(); + case "alloc_array": + return alloc_array.ToPointer(); + case "alloc_array_type": + return alloc_array_type.ToPointer(); + case "val_array_size": + return val_array_size.ToPointer(); + case "val_array_i": + return val_array_i.ToPointer(); + case "val_array_set_i": + return val_array_set_i.ToPointer(); + case "val_array_push": + return val_array_push.ToPointer(); + case "val_id": + return val_id.ToPointer(); + case "alloc_field": + return alloc_field.ToPointer(); + case "val_call0": + return val_call0.ToPointer(); + case "alloc_empty_object": + return alloc_empty_object.ToPointer(); + case "alloc_string_len": + return alloc_string_len.ToPointer(); + case "alloc_wstring_len": + return alloc_wstring_len.ToPointer(); + case "alloc_float": + return alloc_float.ToPointer(); + case "alloc_buffer_len": + return alloc_buffer_len.ToPointer(); + case "buffer_data": + return buffer_data.ToPointer(); + case "buffer_val": + return buffer_val.ToPointer(); + case "val_to_buffer": + return val_to_buffer.ToPointer(); + case "buffer_size": + return buffer_size.ToPointer(); + case "pin_buffer": + return pin_buffer.ToPointer(); + case "unpin_buffer": + return unpin_buffer.ToPointer(); + case "val_field": + return val_field.ToPointer(); + case "val_bool": + return val_bool.ToPointer(); + case "val_throw": + return val_throw.ToPointer(); + } + + return IntPtr.Zero; + } + } +} diff --git a/templates/cs/src/cs/ndll/CSAbstract.cs b/templates/cs/src/cs/ndll/CSAbstract.cs new file mode 100644 index 000000000..f9cb73bf4 --- /dev/null +++ b/templates/cs/src/cs/ndll/CSAbstract.cs @@ -0,0 +1,76 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class CSAbstract : IDisposable + { + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + internal delegate IntPtr FinalizerDelegate(IntPtr arg1); + + internal IntPtr Pointer { get; private set; } + internal int Kind { get; private set; } + private FinalizerDelegate finalizer; + internal FinalizerDelegate Finalizer + { + get + { + return finalizer; + } + set + { + if (disposed && value != null) + throw new InvalidOperationException("Tried to set finalizer to disposed CSAbstract"); + if (finalizer != null && value != null) + throw new InvalidOperationException("Finalizer is already set"); + + finalizer = value; + if (finalizer == null) + { + GC.SuppressFinalize(this); + disposed = true; + } + } + } + private bool disposed; + + internal CSAbstract(int kind, IntPtr ptr) + { + Pointer = ptr; + Kind = kind; + disposed = false; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposed) + return; + disposed = true; + if (finalizer == null) + return; + + GCHandle handle = GCHandle.Alloc(this, GCHandleType.Normal); + finalizer(GCHandle.ToIntPtr(handle)); + handle.Free(); + } + + public void Free() + { + Pointer = IntPtr.Zero; + finalizer = null; + disposed = true; + GC.SuppressFinalize(this); + } + + ~CSAbstract() + { + Dispose(false); + } + } +} \ No newline at end of file diff --git a/templates/cs/src/cs/ndll/CSHandleContainer.cs b/templates/cs/src/cs/ndll/CSHandleContainer.cs new file mode 100644 index 000000000..0393a1af3 --- /dev/null +++ b/templates/cs/src/cs/ndll/CSHandleContainer.cs @@ -0,0 +1,115 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class CSHandleContainer : IDisposable + { + private bool disposed = false; + private System.Collections.Generic.Dictionary sgNameToID; + private System.Collections.Generic.List sgIDToName; + + internal System.Collections.Generic.List handles; + internal System.Collections.Generic.List memoryList; + + private static CSHandleContainer container; + + private CSHandleContainer() + { + sgNameToID = new System.Collections.Generic.Dictionary(); + sgIDToName = new System.Collections.Generic.List(); + + handles = new System.Collections.Generic.List(); + memoryList = new System.Collections.Generic.List(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (disposed) + return; + + for (int i = 0; i < handles.Count; ++i) + handles[i].Free(); + + for (int i = 0; i < memoryList.Count; ++i) + Marshal.FreeHGlobal(memoryList[i]); + + disposed = true; + } + + ~CSHandleContainer() + { + Dispose(false); + } + + internal int GetId(string key) + { + if (sgNameToID.ContainsKey(key)) + return sgNameToID[key]; + int idx = sgIDToName.Count; + sgIDToName.Add(key); + sgNameToID.Add(key, idx); + return idx; + } + + internal string GetStringFromId(int id) + { + return sgIDToName[id]; + } + + internal IntPtr CreateGCHandle(Object value) + { + handles.Add(GCHandle.Alloc(value, GCHandleType.Normal)); + return GCHandle.ToIntPtr(handles[handles.Count - 1]); + } + + internal IntPtr CreatePinnedGCHandle(Object value) + { + handles.Add(GCHandle.Alloc(value, GCHandleType.Pinned)); + return GCHandle.ToIntPtr(handles[handles.Count - 1]); + } + + internal IntPtr GetAddrOfBlittableObject(Object value) + { + handles.Add(GCHandle.Alloc(value, GCHandleType.Pinned)); + return handles[handles.Count - 1].AddrOfPinnedObject(); + } + + internal IntPtr AllocateMemory(int length) + { + IntPtr memory = Marshal.AllocHGlobal(length); + memoryList.Add(memory); + return memory; + } + + internal void ResizeHandles(int handleSize, int memoryListSize) + { + int oldHandleSize = handles.Count; + for (int i = handleSize; i < oldHandleSize; ++i) + { + handles[i].Free(); + } + handles.RemoveRange(handleSize, oldHandleSize - handleSize); + + int oldMemoryListSize = memoryList.Count; + for (int i = memoryListSize; i < oldMemoryListSize; ++i) + Marshal.FreeHGlobal(memoryList[i]); + memoryList.RemoveRange(memoryListSize, oldMemoryListSize - memoryListSize); + } + + internal static CSHandleContainer GetCurrent() + { + if (container == null) + container = new CSHandleContainer(); + + return container; + } + + } +} diff --git a/templates/cs/src/cs/ndll/CSHandleScope.cs b/templates/cs/src/cs/ndll/CSHandleScope.cs new file mode 100644 index 000000000..9afd5dfa8 --- /dev/null +++ b/templates/cs/src/cs/ndll/CSHandleScope.cs @@ -0,0 +1,22 @@ +namespace cs.ndll +{ + struct CSHandleScope + { + internal static CSHandleScope Create() + { + CSHandleScope scope = new CSHandleScope(); + CSHandleContainer container = CSHandleContainer.GetCurrent(); + scope.handleIndex = container.handles.Count; + scope.memoryListIndex = container.memoryList.Count; + return scope; + } + + internal void Destroy() + { + CSHandleContainer.GetCurrent().ResizeHandles(handleIndex, memoryListIndex); + } + + private int handleIndex; + private int memoryListIndex; + }; +} \ No newline at end of file diff --git a/templates/cs/src/cs/ndll/CSPersistent.cs b/templates/cs/src/cs/ndll/CSPersistent.cs new file mode 100644 index 000000000..e92b87936 --- /dev/null +++ b/templates/cs/src/cs/ndll/CSPersistent.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class CSPersistent + { + internal object Value { get; private set; } + + internal CSPersistent(object value) + { + Value = value; + } + + internal void Destroy() + { + Value = null; + } + } +} diff --git a/templates/cs/src/cs/ndll/DelegateConverter.cs b/templates/cs/src/cs/ndll/DelegateConverter.cs new file mode 100644 index 000000000..08cc862d6 --- /dev/null +++ b/templates/cs/src/cs/ndll/DelegateConverter.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class DelegateConverter : IDisposable + { + private T func; + private IntPtr funcPtr; + private GCHandle handle; + + internal DelegateConverter(T func) + { + this.func = func; + } + + ~DelegateConverter() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!handle.IsAllocated) + return; + + handle.Free(); + } + + internal IntPtr ToPointer() + { + if (!handle.IsAllocated) + { + funcPtr = Marshal.GetFunctionPointerForDelegate(func as Delegate); + handle = GCHandle.Alloc(funcPtr, GCHandleType.Pinned); + } + return (IntPtr)handle.Target; + } + } +} \ No newline at end of file diff --git a/templates/cs/src/cs/ndll/HandleUtils.cs b/templates/cs/src/cs/ndll/HandleUtils.cs new file mode 100644 index 000000000..99419f708 --- /dev/null +++ b/templates/cs/src/cs/ndll/HandleUtils.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class HandleUtils + { + internal static bool IsEmpty(GCHandle handle) + { + if (handle == null) + return true; + else if (handle.Target == null) + return true; + + return false; + } + + internal static object GetObjectFromIntPtr(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + return null; + + return GCHandle.FromIntPtr(ptr).Target; + } + } +} diff --git a/templates/cs/src/cs/ndll/NDLLFunction.cs b/templates/cs/src/cs/ndll/NDLLFunction.cs new file mode 100644 index 000000000..95ae3e9b4 --- /dev/null +++ b/templates/cs/src/cs/ndll/NDLLFunction.cs @@ -0,0 +1,272 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + public class NDLLFunction : IDisposable + { + private IntPtr module; + private Delegate func; + private int numArgs; + private static CFFICSLoader.CFFILoaderDelegate loaderDelegate; + private static GCHandle pinnedLoaderFunc; + public static String LibraryDir = null; + public static String LibraryPrefix = ""; + public static String LibrarySuffix = ".ndll"; + + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr NDLLFunctionDelegate(); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate void HxSetLoaderDelegate(IntPtr loader); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr CallMultDelegate(IntPtr args); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call0Delegate(); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call1Delegate(IntPtr arg1); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call2Delegate(IntPtr arg1, IntPtr arg2); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call3Delegate(IntPtr arg1, IntPtr arg2, IntPtr arg3); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call4Delegate(IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4); + [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)] + private delegate IntPtr Call5Delegate(IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5); + + NDLLFunction(IntPtr module, Delegate func, int numArgs) + { + this.module = module; + this.func = func; + this.numArgs = numArgs; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (module != IntPtr.Zero) + { + NativeMethods.FreeLibraryWrap(module); + module = IntPtr.Zero; + } + } + + ~NDLLFunction() + { + Dispose(false); + } + + public static NDLLFunction Load(String lib, String name, int numArgs) + { + if (numArgs < -1 || numArgs > 5) + throw new ArgumentOutOfRangeException("Invalid numArgs: " + numArgs); + + IntPtr module = IntPtr.Zero; + try + { + if (LibraryDir != null && (lib.StartsWith("./") || lib.StartsWith(".\\"))) + lib = LibraryDir + Path.DirectorySeparatorChar + LibraryPrefix + lib.Substring(2) + LibrarySuffix; + else + lib = lib + LibrarySuffix; + module = NativeMethods.LoadLibraryWrap(lib); + if (module == IntPtr.Zero) + return null; + + String funcName; + if (numArgs != -1) + funcName = String.Format("{0}__{1}", name, numArgs); + else + funcName = String.Format("{0}__MULT", name); + + IntPtr funcPtr = NativeMethods.GetProcAddressWrap(module, funcName); + if (funcPtr == IntPtr.Zero) + return null; + NDLLFunctionDelegate func = (NDLLFunctionDelegate)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(NDLLFunctionDelegate)); + Delegate cfunc = null; + switch (numArgs) + { + case -1: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(CallMultDelegate)); + break; + case 0: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call0Delegate)); + break; + case 1: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call1Delegate)); + break; + case 2: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call2Delegate)); + break; + case 3: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call3Delegate)); + break; + case 4: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call4Delegate)); + break; + case 5: + cfunc = Marshal.GetDelegateForFunctionPointer(func(), typeof(Call5Delegate)); + break; + } + + IntPtr dll_hx_set_loader_ptr = NativeMethods.GetProcAddressWrap(module, "hx_set_loader"); + if (dll_hx_set_loader_ptr == IntPtr.Zero) + return null; + HxSetLoaderDelegate dll_hx_set_loader = (HxSetLoaderDelegate)Marshal.GetDelegateForFunctionPointer(dll_hx_set_loader_ptr, typeof(HxSetLoaderDelegate)); + IntPtr callbackPtr; + if (loaderDelegate == null) + { + loaderDelegate = new CFFICSLoader.CFFILoaderDelegate(CFFICSLoader.Load); + callbackPtr = Marshal.GetFunctionPointerForDelegate(loaderDelegate); + pinnedLoaderFunc = GCHandle.Alloc(callbackPtr, GCHandleType.Pinned); + } + else + { + callbackPtr = (IntPtr)pinnedLoaderFunc.Target; + } + + dll_hx_set_loader(callbackPtr); + + NDLLFunction ndllFunc = new NDLLFunction(module, cfunc, numArgs); + module = IntPtr.Zero; + return ndllFunc; + } + finally + { + if (module != IntPtr.Zero) + NativeMethods.FreeLibraryWrap(module); + } + } + + public object CallMult(Array args) + { + if (numArgs != -1) + throw new InvalidOperationException(); + + Array hxArray = (Array)args; + CSHandleScope scope = CSHandleScope.Create(); + GCHandle[] handles = new GCHandle[hxArray.length]; + for (int i = 0; i < hxArray.length; ++i) + handles[i] = GCHandle.Alloc(hxArray[i]); + IntPtr[] pointers = new IntPtr[hxArray.length]; + for (int i = 0; i < hxArray.length; ++i) + pointers[i] = GCHandle.ToIntPtr(handles[i]); + GCHandle pinnedArray = GCHandle.Alloc(pointers, GCHandleType.Pinned); + + CallMultDelegate cfunc = (CallMultDelegate)func; + object result = HandleUtils.GetObjectFromIntPtr(cfunc(pinnedArray.AddrOfPinnedObject())); + scope.Destroy(); + for (int i = 0; i < hxArray.length; ++i) + handles[i].Free(); + pinnedArray.Free(); + return result; + } + + public object Call0() + { + if (numArgs != 0) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call0Delegate cfunc = (Call0Delegate)func; + object result = HandleUtils.GetObjectFromIntPtr(cfunc()); + scope.Destroy(); + return result; + } + + public object Call1(object arg1) + { + if (numArgs != 1) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call1Delegate cfunc = (Call1Delegate)func; + GCHandle gch1 = GCHandle.Alloc(arg1); + object result = HandleUtils.GetObjectFromIntPtr(cfunc(GCHandle.ToIntPtr(gch1))); + scope.Destroy(); + gch1.Free(); + return result; + } + + public object Call2(object arg1, object arg2) + { + if (numArgs != 2) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call2Delegate cfunc = (Call2Delegate)func; + GCHandle gch1 = GCHandle.Alloc(arg1); + GCHandle gch2 = GCHandle.Alloc(arg2); + object result = HandleUtils.GetObjectFromIntPtr(cfunc(GCHandle.ToIntPtr(gch1), GCHandle.ToIntPtr(gch2))); + scope.Destroy(); + gch1.Free(); + gch2.Free(); + return result; + } + + public object Call3(object arg1, object arg2, object arg3) + { + if (numArgs != 3) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call3Delegate cfunc = (Call3Delegate)func; + GCHandle gch1 = GCHandle.Alloc(arg1); + GCHandle gch2 = GCHandle.Alloc(arg2); + GCHandle gch3 = GCHandle.Alloc(arg3); + object result = HandleUtils.GetObjectFromIntPtr(cfunc(GCHandle.ToIntPtr(gch1), GCHandle.ToIntPtr(gch2), GCHandle.ToIntPtr(gch3))); + scope.Destroy(); + gch1.Free(); + gch2.Free(); + gch3.Free(); + return result; + } + + public object Call4(Object arg1, Object arg2, Object arg3, Object arg4) + { + if (numArgs != 4) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call4Delegate cfunc = (Call4Delegate)func; + GCHandle gch1 = GCHandle.Alloc(arg1); + GCHandle gch2 = GCHandle.Alloc(arg2); + GCHandle gch3 = GCHandle.Alloc(arg3); + GCHandle gch4 = GCHandle.Alloc(arg4); + object result = HandleUtils.GetObjectFromIntPtr(cfunc(GCHandle.ToIntPtr(gch1), GCHandle.ToIntPtr(gch2), GCHandle.ToIntPtr(gch3), GCHandle.ToIntPtr(gch4))); + scope.Destroy(); + gch1.Free(); + gch2.Free(); + gch3.Free(); + gch4.Free(); + return result; + } + + public Object Call5(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) + { + if (numArgs != 5) + throw new InvalidOperationException(); + + CSHandleScope scope = CSHandleScope.Create(); + Call5Delegate cfunc = (Call5Delegate)func; + GCHandle gch1 = GCHandle.Alloc(arg1); + GCHandle gch2 = GCHandle.Alloc(arg2); + GCHandle gch3 = GCHandle.Alloc(arg3); + GCHandle gch4 = GCHandle.Alloc(arg4); + GCHandle gch5 = GCHandle.Alloc(arg5); + object result = HandleUtils.GetObjectFromIntPtr(cfunc(GCHandle.ToIntPtr(gch1), + GCHandle.ToIntPtr(gch2), GCHandle.ToIntPtr(gch3), GCHandle.ToIntPtr(gch4), GCHandle.ToIntPtr(gch5))); + scope.Destroy(); + gch1.Free(); + gch2.Free(); + gch3.Free(); + gch4.Free(); + gch5.Free(); + return result; + } + } +} diff --git a/templates/cs/src/cs/ndll/NativeMethods.cs b/templates/cs/src/cs/ndll/NativeMethods.cs new file mode 100644 index 000000000..2bd3b5ad6 --- /dev/null +++ b/templates/cs/src/cs/ndll/NativeMethods.cs @@ -0,0 +1,64 @@ +using System; +using System.Runtime.InteropServices; + +namespace cs.ndll +{ + class NativeMethods + { + public static IntPtr LoadLibraryWrap(String filename) + { + switch(Environment.OSVersion.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + return LoadLibrary(filename); + default: + return dlopen(filename, RTLD_NOW); + } + } + + public static void FreeLibraryWrap(IntPtr handle) + { + switch(Environment.OSVersion.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + FreeLibrary(handle); + break; + default: + dlclose(handle); + break; + } + } + + public static IntPtr GetProcAddressWrap(IntPtr handle, String symbol) + { + switch(Environment.OSVersion.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + return GetProcAddress(handle, symbol); + default: + return dlsym(handle, symbol); + } + } + + internal const int RTLD_NOW = 2; + + [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern IntPtr LoadLibrary(String lpFileName); + [DllImport("kernel32", SetLastError = true)] + private static extern bool FreeLibrary(IntPtr hModule); + [DllImport("kernel32", SetLastError = true, ExactSpelling = false, BestFitMapping = false, ThrowOnUnmappableChar = true)] + private static extern IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)]String lpProcName); + [DllImport("dl", BestFitMapping = false, ThrowOnUnmappableChar = true)] + private static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPTStr)]String filename, int flags); + [DllImport("dl")] + private static extern int dlclose(IntPtr handle); + [DllImport("dl", BestFitMapping = false, ThrowOnUnmappableChar = true)] + private static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPTStr)] String symbol); + } +} diff --git a/tools/svg.hxml b/tools/svg.hxml index baa37191b..d081dde51 100644 --- a/tools/svg.hxml +++ b/tools/svg.hxml @@ -4,5 +4,6 @@ -cp .. -lib openfl -lib svg --D lime_cairo +-D lime-cairo +-D lime-cffi --remap flash:openfl diff --git a/tools/tools.hxml b/tools/tools.hxml index 06f6c4541..fff56ca9f 100644 --- a/tools/tools.hxml +++ b/tools/tools.hxml @@ -1,8 +1,9 @@ -main CommandLineTools -neko tools.n -D lime-curl +-D lime-cffi -D lime -cp .. -lib format #-lib svg --D optional_cffi \ No newline at end of file +-D optional-cffi \ No newline at end of file