2

这是调用代码

unit CY;

interface
uses windows;
type

 TMember_Rd = Record
    iID: integer;
    sCode: Array[0..255] of char;
    sName: Array[0..255] of char;
  end;

  PTMember_Rd = ^TMember_Rd;

function GetMember(sStore, sMachine: PChar; const sTrack, sCode, sVerify: PChar; 
  Member: PTMember_Rd; sError: PChar): Integer; stdcall; external 'Interface.dll';

implementation

end.

我需要调用 GetMember 函数并将数据填充到 Member 中,如果有任何错误,我可以从 sError 获取消息。

我如何调用这个函数?

我不熟悉德尔福;我认为我的错误在于指针。

以下是我的 c# 代码工作

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace JFTest
{
    public class JFService
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct PTMember_Rd
        {
            public Int32 id;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string sCode;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string sName;
        }

        [DllImport("Interface.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern int GetMember(StringBuilder sStore, StringBuilder sMachine, StringBuilder sTrack, StringBuilder sCode, StringBuilder sVerify, ref PTMember_Rd Member, [MarshalAs(UnmanagedType.LPStr)] string sError);

    }
}

而且我没有其他代码,dll是客户发送给我的,他们没有源代码。

4

1 回答 1

1

我认为您的 p/invoke 代码是错误的。你说MembersError是输出参数,其他参数是输入。在这种情况下,p/invoke 应该是:

[DllImport("Interface.dll", CharSet=CharSet.Ansi)]
public static extern int GetMember(
    string sStore, 
    string sMachine, 
    string sTrack, 
    string sCode, 
    string sVerify, 
    ref PTMember_Rd Member, 
    StringBuilder sError
);

假设这是正确的,Delphi 应该如下所示:

type
  TMember_Rd = Record
    iID: integer;
    sCode: Array[0..255] of AnsiChar;
    sName: Array[0..255] of AnsiChar;
  end;

function GetMember(
  sStore: PAnsiChar;
  sMachine: PAnsiChar;
  sTrack: PAnsiChar;
  sCode: PAnsiChar;
  sVerify: PAnsiChar;
  out Member: TMember_Rd;
  sError: PAnsiChar
): Integer; stdcall; external 'Interface.dll';

其中sStoresMachine是指定输入参数的字符串变量。

我们需要使用一个字节AnsiCharPAnsiChar. 您在问题中的代码使用两个字节的 UTF-16CharPChar.

你可以这样称呼它:

var
  sError: AnsiString;
  Member: TMember_Rd;
  retval: Integer;
....
SetLength(sError, 256);
retval := GetMember(
  PAnsiChar(AnsiString(sStore)),
  PAnsiChar(AnsiString(sMachine)),
  PAnsiChar(AnsiString(sTrack)),
  PAnsiChar(AnsiString(sCode)),
  PAnsiChar(AnsiString(sVerify)),
  Member,
  PAnsiChar(AnsiString(sError))
);

sError我不知道需要制作多大的字符串。如果您没有任何文档,则无法找到。最好让它变大并希望最好。如果你没有使它足够大,并且函数尝试写入该缓冲区,那么你有缓冲区溢出。

我假设该Member参数具有纯语义,因为这就是您所说的。如果您需要在使用部分或全部字段时传递数据,请将其更改为var并相应地初始化记录。

于 2013-04-24T17:11:56.757 回答