0

I've been requested to create a .Net dll for an old delphi program. I'm trying to do this with a COM Callable Wrapper, but I keep getting an error when it tries to load the dll (pretty general, something like "I couldn't load the dll"). Here is what the technical documentation says:

The DLL only needs to export one function under the name 'AUTHORIZE'.

function Authorize(InXml: PChar): PChar; stdcall;
(Delphi syntax. May be different in other languages.)

Here is my code for the CCW:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ComCallableWrapper
{
    [Guid("C3FD922A-FB44-47B1-9C0C-8F7FAF57098B")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IAuthorizer
    {
        [DispId(1)]
        string Authorize(string lnpInXml);
    }

    [ProgId("ComCallableWrapper.Authorizer")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Authorizer : IAuthorizer
    {
        public Authorizer()
        {
        }

        public string Authorize(string lnpInXml)
        {
            return "Approved!";
        }
    }
}

I also run this command "regasm /tlb:ComCallableWrapper.tlb ComCallableWrapper.dll /codebase" on the computer where the delphi program is running.

I've been doing some research on google about how delphi invokes functions on a dll, and I found at least 2 ways:

function Authorize(lnpInXml: pchar): pchar; stdcall; external 'DLLName.dll';

and

oleObject := CreateOleObject('ComCallableWrapper.Authorizer');
ShowMessage(oleObject.Authorize('Approved?'));

It looks like COM works a little bit different. Is there a way to change my CCW to work like the first way?

Regards.

camendez
  • 43
  • 3
  • The first way looks like it is for calling into a flat C DLL, not a COM DLL. You will not be able to create such a DLL in .NET. – Moby Disk Jan 28 '14 at 20:38
  • There's 5 billion possible reasons that instantiating a COM DLL won't work. To make it fun, Microsoft made them all return basically the same error code. Can you instantiate your object using the Microsoft OLE/COM Object Viewer? Or with .NET code? Start there before tackling the Delphi side of things. – Moby Disk Jan 28 '14 at 20:40

1 Answers1

0

You con't need COM. And indeed using COM is a mistake because the Delphi program is not looking for a COM DLL.

What you need to do is to export an unmanaged function from your managed C# DLL. That's a little tricky and is in fact not supported. These are your most attractive options:

  1. Use Robert Giesecke's UnmanagedExports.
  2. Write a mixed mode C++/CLI DLL that consumes your C# code. The mixed mode C++/CLI is capable of export native functions using __declspec(dllexport), .def files etc.

If you chose to use UnmanagedExports, the function would look like this:

[DllExport]
public static IntPtr Authorize(string InXml)
{
    // your code goes here, for now return the input value
    return Marshal.StringToHGlobalAnsi(InXml);
}

Implementing the function is a little tricky because you need to return a Delphi PAnsiChar, that is a C++ char*. You cannot use string for the return type and have to use IntPtr. But how do you allocate the string so that it remains valid for the caller to use it. The code above leaks the string in an HGLOBAL.

I can't advise you definitively how to resolve the lifetime of the string. The interface you are coding to is not at all well designed. Only you with more knowledge of the interface are in a position to resolve that issue.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks for your help David, much appreciated. I already tried Unmanaged Exports but I hit a wall there too. Perhaps you can give me a hand with that one here: http://stackoverflow.com/questions/21373901/c-sharp-unmanaged-exports-when-multiple-projects-involved-robert-giesecke – camendez Jan 28 '14 at 22:03
  • Sure I can take a look. What about this question? – David Heffernan Jan 28 '14 at 22:42
  • It's a different approach I was trying for the same problem :(. – camendez Jan 28 '14 at 22:48
  • This is the answer to the question that you asked here I am sure. Your actual problem is more tricky and probably is down to something as yet not understood in the old Delphi app to which you have no source. It"s going to be hard to diagnose. – David Heffernan Jan 28 '14 at 22:54