Skip to content

Instantly share code, notes, and snippets.

@eiriksfa
Created August 21, 2017 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eiriksfa/c0e3b3c161e1024ded8ce45f33b21a77 to your computer and use it in GitHub Desktop.
Save eiriksfa/c0e3b3c161e1024ded8ce45f33b21a77 to your computer and use it in GitHub Desktop.
Pascal C# embedding test
unit Mono;
{$ifdef fpc}
{$mode objfpc}{$H+}
{$endif}
interface
uses
Classes;
type
MonoAssembly = Pointer;
MonoImage = Pointer;
MonoClass = Pointer;
MonoMethod = Pointer;
MonoObject = Pointer;
MonoArray = Pointer;
MonoDomain = Pointer;
MonoMethodDesc = Pointer;
MonoString = Pointer;
MonoParamsArray = array[0..0] of Pointer;
MonoParams = ^MonoParamsArray;
PPAnsiChar = ^PAnsiChar;
IntBool = Integer;
MonoObjectArray = ^MonoObject;
TMonoClass = class;
TMonoAssembly = class
private
assembly_: MonoAssembly;
image_: MonoImage;
public
constructor Create(const assemblyName: String);
function CreateClass(const aClassName: String; const nameSpace: String = ''): TMonoClass;
property Assembly: MonoAssembly read assembly_;
property Image: MonoImage read image_;
end;
procedure Call(assembly: TMonoAssembly; out l: Integer; out p: PChar): Integer;
implementation
uses
CTypes;
//================================
{$LINKLIB mono-2.0}
procedure mono_config_parse(filename: PAnsiChar); cdecl; external;
function mono_jit_init(name: PAnsiChar): MonoDomain; cdecl; external;
procedure mono_thread_attach(domain: MonoDomain); cdecl; external;
function mono_domain_assembly_open(domain: MonoDomain; filename: PAnsiChar): MonoAssembly; cdecl; external;
function mono_jit_exec(domain: MonoDomain; assembly: MonoAssembly; argc: cint; argv: PPAnsiChar): Integer; cdecl; external;
function mono_assembly_get_image(assembly: MonoAssembly): MonoImage; cdecl; external;
function mono_class_from_name(image: MonoImage; nameSpace, name: PAnsiChar): MonoClass; cdecl; external;
function mono_method_desc_new(name: PAnsiChar; includeNameSpace: cint): MonoMethodDesc; cdecl; external;
function mono_method_desc_search_in_class(methodDesc: MonoMethodDesc; aClass: MonoClass): MonoMethod; cdecl; external;
function mono_runtime_invoke(method: MonoMethod; this: MonoClass; params: MonoParams; exc: MonoObjectArray): MonoObject; cdecl; external;
function mono_array_addr_with_size(arr: MonoArray; size: cint; idx: Cardinal): PChar; cdecl; external;
//================================
var
EmbedDomain: MonoDomain;
constructor TMonoAssembly.Create(const assemblyName: String);
var
argc: Integer;
argv: array[0..1] of PAnsiChar;
begin
if EmbedDomain = nil then
begin
mono_config_parse(nil);
EmbedDomain := mono_jit_init('embedtest');
end;
assembly_ := mono_domain_assembly_open(EmbedDomain, PAnsiChar(assemblyName));
argc := 1;
argv[0] := '';
argv[1] := nil;
mono_jit_exec(EmbedDomain, assembly, argc, PPAnsiChar(@argv));
image_ := mono_assembly_get_image(assembly_);
end;
procedure Call(assembly: TMonoAssembly; out l: Integer; out p: PChar);
var
method: MonoMethod;
methodDesc: MonoMethodDesc;
klass: MonoClass;
res: MonoObject;
arr: MonoArray;
str: MonoString;
rOut: PChar;
prm: array[0..2] of Pointer;
begin
klass := mono_class_from_name(assembly.Image, PAnsiChar('EmbedTest'), PAnsiChar('Program'));
methodDesc := mono_method_desc_new(PAnsiChar('Program::Test'), 0);
method := mono_method_desc_search_in_class(methodDesc, class_);
mono_thread_attach(EmbedDomain);
l := 0;
//-
prm[0] := @arr;
prm[1] := @l;
prm[2] := nil;
res := mono_runtime_invoke(method, nil, MonoParams(@prm[0]), nil);
rOut := mono_array_addr_with_size(arr, l, 0);;
p := rOut;
end;
end.
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace EmbedTest
{
class Program
{
static void Main(string[] args)
{
//IntPtr p;
//int len;
//Test1(ref p, out len);
}
static byte[] CreateImage()
{
Bitmap bmp = new Bitmap(600, 600);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.Transparent);
g.FillRectangle(Brushes.Red, 200, 200, 200, 200);
g.Flush();
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
static int Test(out byte[] res, ref int length)
{
res = CreateImage();
length = res.Length;
return 0;
}
}
}
unit Test;
{$ifdef fpc}
{$mode objfpc}{$H+}
{$endif}
interface
uses
Classes, SysUtils, Mono;
type
procedure Test1;
implementation
var
assembly: TMonoAssembly;
procedure Test1;
var
c: TMonoClass;
l: Integer;
p: PChar;
s: TFileStream;
begin
c := assembly.CreateClass('Program', 'EmbedTest');
try
c.GetMethod('Test');
c.Call('Test', l, p);
s := TFileStream.Create('out/test.txt', fmCreate);
try
s.Write(p^, l);
finally
s.Free;
end;
finally
c.Free;
end;
end;
initialization
assembly := TMonoAssembly.Create('~path to .exe~');
finalization
assembly.Free;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment