PDA

View Full Version : Load and Invoke .net at runtime



MouseTrap
22-02-2009, 02:25
This was a neat experiment, something to hold me over till O2H gets released (soon!!!???)

This allows you to load a .net EXE or DLL and call its internal methods. [using Mono]
It should also allow you have .net call back into the script, but im not sure how this would work without function pointers.

Here is the sample script. Excuse the fact that i've used fixed paths.. :roll:

uses "console"
DECLARE function mono_config_parse LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_config_parse" (file as asciiz)
DECLARE function mono_jit_init LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_jit_init" (file as asciiz) as long
DECLARE function mono_set_dirs LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_set_dirs" (asmdir as asciiz, cfgdir as asciiz) 'as long
DECLARE function mono_domain_assembly_open LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_domain_assembly_open" (byval domain as long, file as asciiz) as long
DECLARE function mono_assembly_get_image LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_assembly_get_image" (byval assembly as long) as long
DECLARE function mono_class_from_name LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_class_from_name" (byval image as long, namespace as asciiz, name as asciiz) as long
DECLARE function mono_object_new LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_object_new" (byval domain as long, byval _class as long) as long
DECLARE function mono_runtime_object_init LIB "C:\Dev\Mono-2.2\bin\mono.dll" ALIAS "mono_runtime_object_init" (byval obj as long) as long

Global MonoDomain as long
Global MonoAssembly as long
Global _Image as long
Global _Class as long '//'class' is a keyword, but not in the docs?!?
Global Obj as long
Global AsmFile as asciiz = "C:\Dev\Mono-2.2\bin\TestEmbed.exe" '// can be an 'exe' or 'dll' file

mono_config_parse($nul)
mono_set_dirs("C:\Dev\Mono-2.2\lib", "C:\Dev\Mono-2.2\etc")
'// Load the program and JIT //
MonoDomain= mono_jit_init (AsmFile)
printl MonoDomain
'// Open the assembly and get the handle
MonoAssembly = mono_domain_assembly_open(MonoDomain,Asmfile)
Printl MonoAssembly
'// get the asm instance
_image = mono_assembly_get_image(MonoAssembly)
printl _image
'// Get the class
_class = mono_class_from_name(_image, "Embed", "MyType")
Printl _class
'// create the object in memory
obj = mono_object_new(monodomain, _class)
printl obj
'// Instantiate the object, calling its default constructor
mono_runtime_object_init(obj)

printl "Done!"
sleep 2000


The code for c# 'TestEmbed' is:

using System;

namespace Embed {
class MyType {
int val = 5;
string str = "hello";

MyType () {
Console.WriteLine ("In ctor val is: {0}", val);
Console.WriteLine ("In ctor str is: {0}", str);
}

MyType (int v, byte[] array) {
Console.WriteLine ("In ctor (int, byte[]) got value: {0}, array len: {1}", v, array.Length);
}

void method () {
Console.WriteLine ("In method val is {0}", val);
Console.WriteLine ("In method str is: {0}", str);
}

int Value {
get {
return val;
}
}

string Message {
get {
return str;
}
}

void Values (ref int v, ref string s) {
Console.WriteLine ("In Values () v is {0}", v);
Console.WriteLine ("In Values () s is: {0}", s);
v = val;
s = str;
}

static void Fail () {
throw new Exception ();
}

static void Main () {
/* we do nothing here... */
Console.WriteLine ("This is inside mono...");
}
}
}


And when you run the script it returns:

28462848
28740912
3035256
3036552
34693104
In ctor val is: 5
In ctor str is: hello

Notice the last 2 lines are from the constructor of C# class.

Petr Schreiber
22-02-2009, 08:36
Hi,

this is interesting experiment, I will try to get Mono to see how it works.

EDIT:
I am just wondering - Mono install for Win requieres 300 MB and it wants me to install GTK, it refuses to go without it.

Is there any way to make it just wrap .NET I have already installed? I understand on Linux it needs to install everything, but on Win?

I am not happy from .NET on my hard drive already, and install another solution which duplicates something I have there already seems little odd to me.


Regarding Oxygen, you can go for it even now.

To declare function, see this excrept from Test_OpenGL2.tbasic


;-------------
; DLL bindings
;-------------

var 4 kernel32,user32,GDI32,opengl32,glu32

kernel32=LoadLibrary `kernel32.dll`
user32 =LoadLibrary `user32.dll`
GDI32 =LoadLibrary `GDI32.dll`
opengl32=LoadLibrary `Opengl32.dll`
glu32 =LoadLibrary `glu32.dll`

bind kernel32
(
GetCommandLine GetCommandLineA ; @0
GetModuleHandle GetModuleHandleA ; @4
QueryPerformanceCounter QueryPerformanceCounter ; @4
QueryPerformanceFrequency QueryPerformanceFrequency ; @4
)


To bind array, it should be also easy.

Just declare array elements, and in code reference it by name:


Uses "Oxygen"
dim MyArray(1) as long =41

dim src as string="
;-----------------
; INTEGER
mov eax,[#MyArray]
inc eax
mov [#MyArray],eax
;----------------
...

... you can go through elements by manipulating offset from the first item


But as I said, if you want even more comfort, you should wait till Charles prepares O2H, it is high level syntax compiler... it is not work for one afternoon ;) And the result will be worth the waiting.

MouseTrap
22-02-2009, 08:53
ya, Ive been playing with each new release of o2h since i joined the forums, but getting a handle on what it can and cant do isnt easy from just the test scripts.

I pretty sure this kind of thing doesn't work with MS .net. COM interop is the only way I've seen to call .Net from an unmanaged host. I have been able to compile .Net dll's into static librarys for use with C ect. but that doesnt help.

the Mono package is pretty big i agree and i've ignored mono for all these years until i started researching a scripting engine for my game. I don't believe there is a smaller download version and I wouldn't fault anyone for wanting to keep it off their harddrive.

Petr Schreiber
22-02-2009, 10:37
Hi,

what is your experience with Mono so far? How it looks with compatibility level?
Is it more comfortable than accessing .NET with COM? Who killed John Kennedy? :)

Charles was experimenting with COM in Oxygen too.
You can read more on Oxygen in:
ThinBasic Journal #1 (http://community.thinbasic.com/index.php?topic=1865.0)
ThinBasic Journal #2 (http://community.thinbasic.com/index.php?topic=2310.0)
... and there is some info in thinBasic_Oxygen.chm located in ThinBasic help directory too.


Thanks,
Petr

ErosOlmi
22-02-2009, 10:52
I'm sorry but there is no way to have a real "machine" pinter to thinBasic script functions because thinBasic does not produce any intermediate code. thinBasic is a 100% pure text continuous parser. Script functions are just text that only exists as text. There is no machine code where "jump" to and "return".

Maybe this is a limit but we like that way. We like to optimize it just using text parsing.

Instead what is possible to do is develop thinBasic modules using thinBasic SDK (you can find it under \thinBasic\SDK\ directory after installation).
Inside thinBasic modules it is possible to get a thinBasic pointer to a script function and execute that function whenever you like passing the parameters you prefer. That's the way some thinBasic modules does. For example User Interface (UI) module does it thousands of times per seconds when using dialogs and controls callbacks that are script functions. The same are doing Petr and Michael Hartelf in TBGL and TBEM modules.

To create thinBasic modules you can use different compiled programming language able to produce DLL libraries. We have SDK interfaces for Power Basic (almost all thinBasic programming has been done using Power Basic), FreeBasic (O2H is been developed by Charles using FreeBasic), C, some Delphi. If you are interested we can help and support you in this. The biggest problem we can face to develop thinBasic modules other than PowerBasic and FreeBasic is handling strings: thinBasic used OLE32 dynamic strings to handle all string handling. Not all compilers handle such powerful strings so (in case) we have to find a way to interact with them.

You said you made your AStar dll in BlitzMax. Personally I've never used BlitzMax but as far as it can produce 32bit DLL we can think about it and make some tests.

Ciao
Eros

MouseTrap
22-02-2009, 10:55
what is your experience with Mono so far? How it looks with compatibility level?
It looks pretty good, the underlying bytecode is the same as MS so its very compatable with MS. It can do a lot of things that MS .net cant do. If I don't use it as a scripting solution i'll probably get rid of it as i already have the MS.net sdk installed. As you said it does take a lot of space.

MouseTrap
22-02-2009, 11:12
Thanks Eros,
I'll look into the sdk. The mono sample i posted above was just a test. I was pleased at how easy it is to do in TB.
blitzmax doesn't natively compile to dll, but it does have the ability to directly import .C files and link them so the gcc version of the sdk would work (i think)
I'll look into it.
Is there any official docs on the SDK?
Thanks!

ErosOlmi
22-02-2009, 11:19
Is there any official docs on the SDK?


I started to write it but so far it is not in the help file :oops:

You can get info looking at thinBasic.inc file you will find in PowerBasic and FreeBasic SDK zip file. That incluide file (especially the PowerBasic one) contains all the SDK functions commented. You can also have an idea on how to develop a module in TBJ (thinBasic Journal) issue 2 (http://community.thinbasic.com/index.php?topic=2310.msg17554#msg17554). I wrote an article that gives some starting idea on how to interact with thinBasic Core engine.

Eros

MouseTrap
22-02-2009, 12:08
Thats a great article about the SDK! when will there be a next one you refer to in the article?

ErosOlmi
22-02-2009, 12:10
I hope for the next TBJ.