3

I use Unmanaged Exports to create a native .dll from .NET .dll so I can access .NET code from Delphi without COM registration.

For example I have this .NET assembly:

using System;
using System.Collections.Generic;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace DelphiNET
{
   [ComVisible(true)]
   [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
   [Guid("ACEEED92-1A35-43fd-8FD8-9BA0F2D7AC31")]
   public interface IDotNetAdder
   {
      int Add3(int left);
   }

   [ComVisible(true)]
   [ClassInterface(ClassInterfaceType.None)]
   public class DotNetAdder : DelphiNET.IDotNetAdder
   {
      public int Add3(int left)
      {
         return left + 3;
      }
   }

   internal static class UnmanagedExports
   {
      [DllExport("createdotnetadder", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
      static void CreateDotNetAdderInstance([MarshalAs(UnmanagedType.Interface)]out IDotNetAdder instance)
      {
         instance = new DotNetAdder();
      }
   }
}

When I define the same interface in Delphi, I can easily use the .NET object:

type
  IDotNetAdder = interface
  ['{ACEEED92-1A35-43fd-8FD8-9BA0F2D7AC31}']
    function Add3(left : Integer) : Integer; safecall;
  end;

procedure CreateDotNetAdder(out instance :  IDotNetAdder); stdcall;
  external 'DelphiNET' name 'createdotnetadder';

var
  adder : IDotNetAdder;
begin
  try
   CreateDotNetAdder(adder);
   Writeln('4 + 3 = ', adder.Add3(4));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

See my Delphi question and answers for details.

My question:
Is something like this possible in FoxPro? I've tried the following which fails with Data type mismatch error on line createdotnetadder(@ldnw):

DECLARE createdotnetadder IN DelphiNET.dll object @ ldnw
ldnw = 0
createdotnetadder(@ldnw)
loObject = SYS(3096, ldnw)
? loObject.Add3(4)

Can I define interface in FoxPro similarly how I did it in Delphi? If not, can I use this .dll from FoxPro at all? I use Visual FoxPro 9.0 SP2. Thanks.

Community
  • 1
  • 1
Lukas Cenovsky
  • 5,476
  • 2
  • 31
  • 39

2 Answers2

1

It seems that the simplest approach is to live with COM Registration. The alternate approach is to manually host the CLR. Rick Strahl has an extensive post on how do do this from FoxPro:

http://www.west-wind.com/wconnect/weblog/ShowEntry.blog?id=631

Brian Vander Plaats
  • 2,257
  • 24
  • 28
  • Unfortunately, CLR hosting does not work for me. The .NET code intesively use threads and I got Loader Lock exception when quiting the foxpro app. – Lukas Cenovsky Mar 03 '10 at 22:33
  • Well then you probably want to host the CLR out of process. You mentioned in your Q that you got Delphi/UnmangedExports working - is that running inprocess or out of process? – Brian Vander Plaats Mar 04 '10 at 14:32
  • Delphi was in process but you had to tweak floating point exception handling. Anyway, I've moved to COM - it is easier although I am afraid of registration problems on end user computers. – Lukas Cenovsky Apr 05 '10 at 12:33
  • If you're getting loader lock exceptions they are due to unreleased threads. You need to make sure you shut down threads before you close your FoxPro app or VFP will crash while shutting down. This is standard fare and really has nothing to do with COM interop - the same thing will happen in a .NET or Win32 app that uses threads and has outstanding threads running. – Rick Strahl Mar 17 '17 at 23:14
0

You can also use the open source wwDotnetBridge project which automates the CLR runtime hosting processes for you and provides a host of other support features that make it easier to consume .NET types and structures in FoxPro.

loBridge = CREATEOBJECT("wwDotnetBridge","V4")
loBridge.LoadAssembly("MyAssembly.dll")
loInstance = loBridge.CreateInstance("MyNamespace.MyClass")

loInstance.DoSomething(parm1)
loBridge.InvokeMethod(loInstance,"SomeOtherMethodWithUnsupportedTypeParms",int(10))

wwDotnetBridge handles object creation for you and passes back COM instance just as native COM interop does, but it provides additional features otherwise not accessible through COM Interop:

  • Access to static methods and members
  • Access to value types
  • Support for updating arrays and collections
  • Support for overloaded methods and constructors
  • Access to generic types

and many helpers to let you work around the limitations in the COM->.NET mappings provided.

Rick Strahl
  • 17,302
  • 14
  • 89
  • 134