Импортировать Pchar Delphi DLL в C #? - PullRequest
4 голосов
/ 23 февраля 2011

У меня есть процедура в Delphi:

procedure PasswordDLL(month  integer; password  pchar); 
export;

Процедура должна вывести пароль в "пароль" pchar, который я передал в .. Из того, что я гуглюсь .. и читаю .... ref: ЗДЕСЬ и ЗДЕСЬ

Я придумываю:

[DllImport(
    "DelphiPassword.dll",
    CallingConvention = CallingConvention.StdCall,
    CharSet = CharSet.Ansi,
EntryPoint = "PasswordDLL")]
public static extern void PasswordDLL(    
    int month,
    [MarshalAs(UnmanagedType.LPStr)] string password
    ); 

Тогда, когда я позвоню:

string pass = "";
PasswordDLL(2, pass);

То есть пароль для вывода в строку «pass».

Но я получу, что BadImageFormatException не обработано: была предпринята попытка загрузить программу с неверным форматом. (Исключение из HRESULT: 0x8007000B)

Похоже, формат функции, который я использовал, неверен? Интересно, использовал ли я неверный UnmanagedType для PChar, но, судя по чтению, это либо LPWStr, либо LPStr ... Я что-то пропустил?

Заранее спасибо ...

1 Ответ

2 голосов
/ 23 февраля 2011

Прежде всего, поскольку вы не указали, какую версию Delphi вы используете, я отвечу, предполагая, Delphi 6 ни по какой другой причине, чем я знаком с ней.

Ваша процедура Delphi не определяет соглашение о вызовах в своем объявлении, поэтому она не будет использовать stdcall согласно вашему импорту. Он будет использовать соглашение по умолчанию Delphi register , которое помещает первые несколько параметров в регистры, а не в стек. Если вы можете изменить свою DLL-библиотеку Delhpi, добавьте stdcall; после объявления и перестройки, и ваши соглашения о вызовах будут совпадать.

В таблице ниже приведены соглашения о вызовах.

Directive Parameter order Clean-up Passes parameters in registers?
--------- --------------- -------- -------------------------------
register  Left-to-right   Routine  Yes
pascal    Left-to-right   Routine  No
cdecl     Right-to-left   Caller   No
stdcall   Right-to-left   Routine  No
safecall  Right-to-left   Routine  No

Глядя на документацию .NET, похоже, что нет соглашения о вызовах, которое соответствует соглашению Delphi register ( см. Таблицу ниже ), поэтому я думаю, что единственным вариантом может быть изменение соглашение в Delphi DLL.

Member name   Description
-----------   ------------------------ 
Cdecl         The caller cleans the stack. This enables calling functions with   varargs, which makes it appropriate to use for methods that accept a variable number of parameters, such as Printf.
FastCall      This calling convention is not supported.
StdCall       The callee cleans the stack. This is the default convention for calling unmanaged functions with platform invoke.
ThisCall      The first parameter is the this pointer and is stored in register ECX. Other parameters are pushed on the stack. This calling convention is used to call methods on classes exported from an unmanaged DLL.
Winapi        Supported by the .NET Compact Framework. This member is not actually a calling convention, but instead uses the default platform calling convention. For example, on Windows the default is StdCall and on Windows CE .NET it is Cdecl.

Ваш Delphi (6) Pchar (указатель на строку ANSI с нулевым символом в конце) выглядит правильно.

...