2

Delphi で作成された dll ライブラリの使用に問題があります。ソースはありません-dllとインターフェースのみです。C++ プログラムにインポートしたい。ロードに QT を使用する必要はありません (ただし、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);
}

助けてくれてありがとう。

4

1 に答える 1

0

You should mention calling conversion in your typedef:

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

Invalid calling conversion leads to stack corruption. It can explain every incorrect behavior.

You can try to simulate Delphi dynamic array memory layout (mentioned here) with the follwing code:

#pragma pack (push, 1)

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

Then call function using DelphiArray like this

DelphiArray<N> arr;
arr._refCounter = 1;
arr._size = N;
//fill arr.array here
myFunc(arr.array);
于 2012-10-25T18:58:53.543 に答える