【问题标题】:DLL function that exports a pointer do Delphi program导出指针的DLL函数做Delphi程序
【发布时间】:2019-01-20 20:39:57
【问题描述】:

我有一个导出 DLL 的简单程序,这个 DLL 从另一个 DLL 导出函数:

// SDK_DLL.cpp : 

#include "functions.h"
#include "functions_advanced.h" 
#include "stdafx.h"
#include <stdio.h>
using namespace std;

extern "C"
{
    __declspec(dllexport) void DisplayHelloFromDLL()
    {
        printf("Hello from DLL...");
    }

    __declspec(dllexport) function_config FuncInit = appd_config_init();

    __declspec(dllexport) function_config * FuncInit2()
    {
        function_config* cfg = function_config_init();
        return cfg;
    }
}

function_config_init() 返回一个指针,我似乎找不到做出正确导出声明的方法。

我正在通过这种方式将一个简单的函数加载到 Delphi:

procedure DisplayHelloFromDLL; external 'C:\Users\Administrator\Documents\Visual Studio 2017\Projects\SDK_DLL\Debug\SDK_DLL.dll';

是否需要更改加载此指针返回函数的方式?

非常感谢您的帮助。

【问题讨论】:

  • 程序错误,因为它得到了错误的调用约定。很难知道你的意思。你想知道函数的 Delphi 语法。您肯定会在文档中找到它。你不能像这样学习一门语言,在 SO 上问这些问题。你也不能指望通过互操作项目来学习。

标签: c++ delphi


【解决方案1】:

FuncInit 是一个导出变量。 Delphi 不支持通过external 导入变量,只支持函数。如果需要导入FuncInit,则必须直接使用GetProcAddress()在运行时获取指向变量的指针:

type
  // you did not show the C/C++ declaration
  // of function_config, so I can't provide
  // a translation here, but it is likely to
  // be a struct, which is a record in Delphi ...
  function_config = ...;
  pfunction_config = ^function_config;

function GetFuncInit: pfunction_config;
begin
  Result := pfunction_config(GetProcAddress(GetModuleHandle('SDK_DLL.dll'), 'FuncInit'));
end;

var
  FuncInit: pfunction_config;

FuncInit := GetFuncInit;

为了跨语言/编译器的互操作,唯一可移植的调用约定是cdeclstdcall。当代码中没有指定调用约定时,大多数 C 和 C++ 编译器使用的默认值是 __cdecl(但通常可以在编译器设置中指定),而 Delphi 使用的默认值是 register(C 中的 __fastcall ++生成器)。

当没有使用参数或返回值时,比如DisplayHelloFromDLL(),那么声明错误的调用约定并不重要。但是当使用参数和/或返回值时,比如FuncInit2(),那么声明正确的调用约定很重要。详情请见Pitfalls of converting

因此,有问题的两个 DLL 函数可能需要在 Delphi 中声明如下:

type
  function_config = ...;
  pfunction_config = ^function_config;

procedure DisplayHelloFromDLL; cdecl; external 'SDK_DLL.dll' name '_DisplayHelloFromDLL';
function FuncInit2: pfunction_config; cdecl; external 'SDK_DLL.dll' name '_FuncInit2';

如果 DLL 使用 .def 文件从导出的名称中删除名称修改,您可以省略 name 属性:

type
  function_config = ...;
  pfunction_config = ^function_config;

procedure DisplayHelloFromDLL; cdecl; external 'SDK_DLL.dll';
function FuncInit2: pfunction_config; cdecl; external 'SDK_DLL.dll';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    相关资源
    最近更新 更多