【问题标题】:COM Callable Wrapper not working when called from delphi program从delphi程序调用时COM Callable Wrapper不工作
【发布时间】:2014-01-28 20:31:23
【问题描述】:

我被要求为一个旧的 delphi 程序创建一个 .Net dll。我正在尝试使用 COM Callable Wrapper 来执行此操作,但是当它尝试加载 dll 时,我一直收到错误消息(很笼统,例如“我无法加载 dll”)。以下是技术文档的内容:

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.)

这是我的 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!";
        }
    }
}

我还在运行 delphi 程序的计算机上运行此命令“regasm /tlb:ComCallableWrapper.tlb ComCallableWrapper.dll /codebase”。

我一直在google上做一些关于delphi如何调用dll上的函数的研究,我发现至少有两种方式:

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

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

看起来 COM 的工作方式有点不同。有没有办法让我的 CCW 像第一种方式一样工作?

问候。

【问题讨论】:

  • 第一种方法看起来像是调用平面 C DLL,而不是 COM DLL。您将无法在 .NET 中创建这样的 DLL。
  • 实例化 COM DLL 不起作用的可能原因有 50 亿个。为了让它变得有趣,微软让它们都返回基本相同的错误代码。您可以使用 Microsoft OLE/COM 对象查看器实例化您的对象吗?还是使用 .NET 代码?在处理 Delphi 方面的问题之前从那里开始。

标签: c# delphi dll ccw


【解决方案1】:

您不需要 COM。并且确实使用 COM 是一个错误,因为 Delphi 程序不是在寻找 COM DLL。

您需要做的是从您的托管 C# DLL 中导出一个非托管函数。这有点棘手,实际上不受支持。这些是您最有吸引力的选择:

  1. 使用 Robert Giesecke 的UnmanagedExports
  2. 编写一个使用 C# 代码的混合模式 C++/CLI DLL。混合模式 C++/CLI 能够使用__declspec(dllexport)、.def 文件等导出本机函数。

如果您选择使用 UnmanagedExports,该函数将如下所示:

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

实现该函数有点棘手,因为您需要返回一个 Delphi PAnsiChar,即 C++ char*。您不能使用string 作为返回类型,而必须使用IntPtr。但是如何分配字符串,以便调用者使用它仍然有效。上面的代码泄漏了HGLOBAL 中的字符串。

我不能明确地建议您如何解决字符串的生命周期。您正在编码的界面根本没有设计好。只有对界面有更多了解的您才能解决该问题。

【讨论】:

  • 感谢您的帮助大卫,非常感谢。我已经尝试过 Unmanaged Exports,但我也在那里碰壁了。也许你可以在这里帮我一把:stackoverflow.com/questions/21373901/…
  • 当然可以看看。这个问题呢?
  • 这是我为同一问题尝试的不同方法 :(.
  • 这是您在这里提出的问题的答案,我敢肯定。您的实际问题更加棘手,可能是由于您没有来源的旧 Delphi 应用程序尚未理解的问题。这将很难诊断。
猜你喜欢
  • 1970-01-01
  • 2012-02-25
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 2020-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多