9

I'd like to dynamically load and use a .Net assembly created in C# from a Delphi Win32 application. My classes and interfaces are marked as ComVisible, but I would like to avoid registering the assembly. Is this possible?

P.S. I found here link text another good discussion on the topic, but it is more around hosting the CLR. Which begs a question - why would you host CLR versus using ClrCreateManagedInstance?

Community
  • 1
  • 1
Sergey Aldoukhov
  • 22,316
  • 18
  • 72
  • 99
  • By hosting the CLR you gain control of memory management and exception handling hooks that were created to allow things like IIS and SQL Server to control many aspects of how CLR operates. – dthorpe May 20 '11 at 01:39
  • @dthorpe Also it looks like CLR hosting is the only option if you want to use .Net4. Do you know if it has more overhead vs. ClrCreateManagedInstance or registered COM instantiation? – Sergey Aldoukhov May 21 '11 at 04:40
  • I would think the overhead would be the same. In all three cases, the CLR has to be loaded into the process. The only difference is who / how the load is initiated. – dthorpe May 23 '11 at 16:53

3 Answers3

8

Strangely enough, I couldn't find an answer on StackOverflow, and there is not much on the Net, especially for Delphi. I found the solution from examples posted here. Here's what I got at the end:

function ClrCreateManagedInstance(pTypeName: PWideChar; const riid: TIID;
out ppObject): HRESULT; stdcall; external 'mscoree.dll';

procedure TMyDotNetInterop.InitDotNetAssemblyLibrary;
var
  MyIntf: IMyIntf;
hr: HRESULT;
NetClassName: WideString;
begin
//Partial assembly name works but full assembly name is preffered.
    NetClassName := 'MyCompany.MyDLLName.MyClassThatImplementsIMyIntf,
          MyCompany.MyDLLName';
    hr := ClrCreateManagedInstance(PWideChar(NetClassName), IMyIntf, MyIntf);
    //Check for error. Possible exception is EOleException with ErrorCode
    //FUSION_E_INVALID_NAME = $80131047 2148732999 : The given assembly name 
    //or codebase was invalid.
    //COR_E_TYPELOAD = $80131522 - "Could not find or load a specific type 
    //(class, enum, etc)"
    //E_NOINTERFACE = $80004002 - "Interface not supported".
    OleCheck(hr);
end;

BTW, depending on the situation, you might want to load mscoree.dll dynamically, because it might be not present on the system (XP with no .Net Framework)

EDIT: Unfortunately, this was deprecated and stopped working with .Net4 as I just found out. This leaves only two options - CLR hosting and unmanaged export. Also, debugging of .Net4 COM code is broken.

Community
  • 1
  • 1
Sergey Aldoukhov
  • 22,316
  • 18
  • 72
  • 99
  • 2
    Note that unless you've already loaded the CLR into your process, ClrCreateManagedInstance will try to load the runtime v1.0.3705 before trying to load the latest version... which may cause some interesting behavior. – Neil Williams Apr 24 '09 at 19:53
1

Maybe using RegFreeCOM and a COm-Callable Wrapper.

http://msdn.microsoft.com/en-us/magazine/cc188708.aspx

Jonathan Allen
  • 68,373
  • 70
  • 259
  • 447
  • As far as I understand, RegFreeCOM is for accessing COM from .NET. My question was about accessing COM enabled .Net from native code. – Sergey Aldoukhov Aug 09 '09 at 19:30
0

Unfortunately this can't be done (to my knowledge) without exposing a COM object, as .NET dll's are not TRULY compiled to a library that Delphi (or anything else) can load, since that is all done by the JIT compiler at runtime.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343