【问题标题】:how to call function in c++ from delphi compiled dll如何从delphi编译的dll调用c++中的函数
【发布时间】:2012-10-25 18:50:52
【问题描述】:

我在使用 delphi 制作的 dll 库时遇到问题。我没有它的来源——只有 dll 和接口。我想在我的 c++ 程序中导入它。我不需要使用 QT 进行加载(但这可能是最好的选择)——标准的 Windows api 也适用。

首先,dll的接口:

Unit VPInterface;
interface

type
 TSignal     = array of double;
 ShortVector = array[0..11] of double;

function VP(s: TSignal): ShortVector; stdcall;
 stdcall external 'VoicePrint.dll' name 'VP';

implementation

End {VPInterface.pas}.

QT版本:

typedef double* (*VPFunct)(double[]);
vector<double> v_double;
// put some values in v_double
QLibrary lib("VoicePrint.dll");
VPFunct vpfunct = (VPFunct) lib.resolve("VP");
if (vpfunct) {
  double * res = vpfunct(&v_double[0]);
}
  1. 调用了函数并返回了一些输出,但它是垃圾。如您所见,我传递了内部向量的数组 (&v_double[0])。我尝试在堆栈上使用双数组,但函数尚未完成。谁能解释一下为什么?
  2. 为什么我没有看到正确的结果?我在 C# 中有类似的代码,它可以工作:

    namespace WAT_DLL_TEST
    {
    public class VoicePrint
    {
        [DllImport("VoicePrint.dll", CharSet = CharSet.Ansi, EntryPoint = "VP", CallingConvention = CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.Struct)]
        public static extern ShortVector VP(double[] signal);
    
    
        [StructLayout(LayoutKind.Explicit, Size = 48)]
        public unsafe struct ShortVector
        {
            [FieldOffset(0)]
            public fixed double m_buffer[6];
        }
    
    }
    }
    

结构可能是实际问题吗?

这是我使用 windows api 运行它的代码:

HINSTANCE hinstDLL;
VPFunct myFunct;
BOOL fFreeDLL;

hinstDLL = LoadLibrary(L"VoicePrint.dll");
if (hinstDLL != NULL)
{
    myFunct = (VPFunct) GetProcAddress(hinstDLL, "VP");
    if (myFunct != NULL) {
        double * dptr = myFunct(&v_double[0]);
        for(int i=0; i<11; i++)
            cout << dptr[i] << endl;
    }
    fFreeDLL = FreeLibrary(hinstDLL);
}

感谢您的帮助。

【问题讨论】:

  • 我正在使用 mingw 4.4 和 qt 4.8。
  • VoicePrint.dll 和 s.txt 在这里:speedyshare.com/naVrr/lib.rar。 s.txt 定义了需要传递给 VP 函数的双精度数。

标签: c++ qt dll


【解决方案1】:

您应该在typedef 中提及调用转换:

typedef double* (__stdcall *VPFunct)(double[]);

无效的调用转换会导致堆栈损坏。它可以解释每一个不正确的行为。

您可以尝试使用以下代码模拟Delphi动态数组内存布局(提到here):

#pragma pack (push, 1)

template <uint32_t size>
struct DelphiArray
{
    uint32_t _refCounter;
    uint32_t _size;
    double array[size];
};
#pragma pack (pop)

然后像这样使用DelphiArray调用函数

DelphiArray<N> arr;
arr._refCounter = 1;
arr._size = N;
//fill arr.array here
myFunc(arr.array);

【讨论】:

  • 不起作用。我试过了,也试过了: typedef double* (__stdcall *VPFunct)(double[]);我会说行为是相同的,所以默认情况下可能是 __stdcall ?
  • @waldek,C# 函数是否返回正确的数据?它像往常一样调用吗?根据doc,Delphi 动态数组有一些非平凡的布局。您可能需要模拟它。 __stdcall 不是默认值。 _cdecl 是默认值。
  • 是的,c# 代码可以正常工作。问题是每次我在 c++ 中都有不同的结果,所以我想我正在读取错误的内存地址或指针布局错误或数据解释错误。我会尝试将它包裹在 struct 周围。
  • @waldek,由于具有负索引的复杂动态数组内存布局,更有可能在将参数传递给函数时发生问题,而不是作为回报,即静态数组,这非常简单(根据给出的文档)。另请注意,虽然不同的结果表明存在问题,但相同的结果并不能证明正确性。
  • 是的,我也无法弄清楚为什么在传递任何本地参数时会出现问题。我主要在 unix 下使用库,但我从来没有遇到过属性问题。此外,我有一个使用 dll 的示例应用程序,结果与 c# 中的相同。
猜你喜欢
  • 2017-12-14
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多