There was a task to pull C # methods from Pascal code.

The main condition for the decision is:
everything should be portable, without the need to register any COM objects and work with Delphi 7 + KOL.

Unfortunately, Pascal / Delphi is not familiar with, a quick reading of the manuals does not give any results, and there is a catastrophic lack of time to learn the language.

The task was partially solved after getting acquainted with:

Export functions from .NET Framework dll to Metatrader
How to open the C # world from MQL5 by exporting unmanaged code
C # Project Template for Unmanaged Exports
Export Managed Code as Unmanaged
Unmanaged Exports ".NET DllExport"

Calling Pascal methods from C # code works, I have no complaints yet.

C# (dll) ... static int test = 0; [System.Reflection.Obfuscation(Feature = "DllExport")] static int Get(){ return test; } [System.Reflection.Obfuscation(Feature = "DllExport")] static void Set(int val){ test = val; } ... Pascal ... function Get(): integer; stdcall; external 'UnmanagedExport.dll'; procedure Set(vl:integer ); stdcall; external 'UnmanagedExport.dll'; ... 

But with calls to Pascal functions from C #, it’s still empty. I tried a simple bike

 C# (dll) ... delegate void del(int val); ... [System.Reflection.Obfuscation(Feature = "DllExport")] static void Test(del proc){ proc(1234); } ... Pascal ... type myProc=procedure(val: integer); ... function Test(fn: myProc): integer; stdcall; external 'UnmanagedExport.dll'; procedure mycall(val: integer); ... procedure mycall(val: integer); ShowMessage(Int2Str(val)); end; ... Test(mycall); ... ... 

The interaction from C # is quite realizable, since the message is triggered, but with garbage.
But how to implement everything correctly is a question.
In addition to calls, I am also interested in the possibility (and how correctly) to subscribe to C # events in Pascal code.


10/11/2016

Good day.

The task has already been resolved, I did not wait for an answer and decided to dig deeper on my own. And unsubscribe all hands did not reach.

Since the task did not include tight integration, the results obtained were quite enough. Using the described method in Exporting functions from Net dll to Metatrader, we got a bridge in the form of an additional dll.

Of the Delphi 4.7 + Kol 1.9, FPC 3.0 (Lazarus) and FPC 2.6 + Kol 3.2 on hand, the code section showed different results. Although in general, after minor edits, the template is applicable to all experimental subjects.

This is just an experiment to understand where to go. For these versions, delphi 4.7 + Kol 1.9 (is the main condition) with its own (not known to me) options and edits in kol-e, this code is operable, although I have not used it in the given scale.

In short, in general terms, the experiment looks like this

 C# public class Class1 { public delegate void del([MarshalAs(UnmanagedType.AnsiBStr)]string _string); [System.Reflection.Obfuscation(Feature = "DllExport")] public static unsafe int Test(int value1, string value2, [MarshalAs(UnmanagedType.AnsiBStr)] ref string value3, del value4, byte* value5) { MessageBox.Show("value1: " + value1.ToString()+ "\r\n" + "value2: " + value2 + "\r\n" + "value3: " + value3 + "\r\n" + "value5: " + value5[1].ToString(), "C#"); value3 = "C# йцукен"; value4("bla-bla бла-бла"); value5[1] = 123; return 54321; } } 

 Pascal ... type myProc=procedure(val: String); StdCall; function Test(val1: integer; val2: string; var val3: string; val4: myProc; val5: pointer): integer; stdcall; external 'ClassLibrary1.dll'; procedure myCall(val: String); StdCall; ... var vl1: string; vl2: array [0..5] of byte; vl3: integer; begin vl1:= 'ytrewq некуцй'; vl2[1]:= 10; vl3:= Test(12345, 'qwerty йцукен', vl1, @myCall, @vl2); ShowMessage('vl1: ' + vl1 + #13#10 + 'vl2: ' + int2str(vl2[1]) + #13#10 + 'vl3: ' + int2str(vl3)); ... procedure myCall(val: String); StdCall; begin ShowMessage('myCall: ' + val); end; 

...

PS Although the goal has been achieved, the question still remains valid, especially the interaction from pascal without bridges, a separate interest in the events.


@Pavel Mayorov. Try to study COM nevertheless ...
Unfortunately, my knowledge in Pascal is very limited, and it is meaningless to learn something new without having initial knowledge. This option is not excluded, but postponed until better times (until more free time appears)

  • Are all exported types and their members in C # made public? - Alexander Petrov
  • @Alexander Petrov. Yes, all by analogy with the code from the first link about Metatrader, just a message was written from memory. - Tomas
  • Try to study all the same COM. They are quite portable and do not require registration. You can simply return them from the exported function. - Pavel Mayorov

2 answers 2

The second article gives an example of C, which can be translated into Pascal:

 #include <stdio.h> #include <string.h> typedef void (__stdcall *callback)(wchar_t * str); extern "C" __declspec(dllexport) void __stdcall caller(wchar_t * input, int count, callback call) {      for(int i = 0; i < count; i++) { call(input); } } 

And this is what Pascal looks like:

 type TCallback = procedure(str: ^Char); stdcall; procedure caller(input: ^Char, count: Integer; call: TCallback); stdcall; var i: Integer; begin for i := 1 to count do call(input); end; 

Your code is almost the same, but the calling function is implemented in C #, while under the article it should be implemented in Pascal (here it is called caller and in Pascal terminology is a procedure).

PS Pascal did not write for 200 years, so syntax flaws are possible in the code.

  • stdcall lost ... - Pavel Mayorov
  • @PavelMayorov For some reason I’ve got it stuck in my memory that Pascal defaults to stdcall , so I didn’t specify. On the other hand, it is more correct to indicate explicitly, in the end, is it possible to find some compilation keys? - Mark Shevchenko
  • Pascal uses the pascal convention by pascal from the day it appeared ... - Pavel Mayorov
  • one
    By the way, in Delphi, the stdcall agreement is also not implemented quite standardly, which is why it is not recommended to return anything other than numbers. - Pavel Mayorov

For non-cross-platform interaction there is a CLR hosting in unmanaged application.

By the way, the question of interaction in Delphi

https://stackoverflow.com/questions/39918962/get-value-of-property-of-type-struct

But Host CLR uses COM no matter what. Therefore, it is easier to use the COM wrapper to access any .Net Classes.

How to call a method from C # to 1C?

Delphi will look like this.

  Wrapp:= CreateoieObject('NetObjectToIDispatch45'); Infrascturcture:=Wrapp.ПолучитьТипИзСборки("HelloWorldLibrary.Infrascturcture",ПутьКСборке_Или_Имя_ДЛЛ_Если_В_GAС); Foo:=Infrascturcture.Foo(); 

For cross-platform, it is possible to use static .Net assembly methods through CoreClr.Dll. Cross-platform use of .Net classes from unmanaged code. Or analogue IDispatch on Linux

Well, here all my articles on using CoreClr in 1C https://habrahabr.ru/users/serginio1/topics/

  • Please include in the answer the main points, and use the links only as a supplement. - Kromster
  • There is not easy to describe the moments. Even the links have little information. But by hosting CLR I will write more examples - Serginio