我只有来自客户的API描述的DLL和文本文件(见下文)。我没有关于DLL的更多细节。我不知道Delphi版本等。
我尝试使用两种API函数,但没有成功。通常,字符串[255](PatientID和AccessionNo)的前两个参数很重要。我尝试将字符串传递给该DLL的任何尝试都无法提供正确的结果。我在应用程序GUI中看到随机垃圾值或部分字符串。我查看了这个网站上的所有相关问题,并在互联网上搜索,但没有找到任何帮助我的东西。
OpenStudy函数 - 我尝试了CharSet = CharSet.Ansi和Auto的不同设置,对于MarshalAs所有合适的值(见下文)。 我在托管应用程序GUI文本字段中看到了垃圾随机值。
[DllImport("Lib\\RISInterface.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "Open_Study", ExactSpelling = false)]
static extern internal int OpenStudy(
// try to use here and for all string fields [MarshalAs(UnmanagedType.AnsiBStr)] , LPStr, LPTStr, LPWStr, BStr, TBStr, HString
string PatientID,
string AccessionNo,
bool CloseCurrentStudy,
bool AddToWindow,
int SeriesRows,
int SeriesCols,
int PresentationMode,
bool AutoTile,
bool AutoLoad,
bool RemoteExam);
OpenStudy1函数 - 我填充结构和调用函数。我将PatientID和AccessionNo视为普通字符串,但PatientID错过了第一个字母而AccessionNo错过了前两个字母。 (发送:“qwerty”,“12345”并参见:“werty”,“345”)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TIQStudyAutomation
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string PatientID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string AccessionNo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string StudyUID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string SeriesUID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string InstanceUID;
public bool CloseCurrentStudy;
public bool AddToWindow;
public int SeriesRows;
public int SeriesCols;
public int PresentationMode;
public bool AutoTile;
public bool AutoLoad;
public bool RemoteExam;
public bool LoadFromAllSources;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string ArchiveName;
}
[DllImport("Lib\\RISInterface.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "Open_Study1", ExactSpelling = false)]
static extern internal int OpenStudy1(TIQStudyAutomation automationInfo);
================= API描述============================ ==============
这些函数声明是Delphi Code,所有字符串引用都是Ansi字符串。
function Open_Study(PatientID, AccessionNo: PAnsiChar; CloseCurrentStudy, AddToWindow: Boolean;
SeriesRows, SeriesCols, PresentationMode: Integer;
AutoTile, AutoLoad, RemoteExam: Boolean): Integer; stdcall;
Return
Error Code.
Remarks
The parameters will be packed into a TIQStudyAutomation record and passed to Open_Study1.
//--------------------------------------------------------------------------------------------------
function Open_Study1(AutomationInfo: TIQStudyAutomation): Integer; stdcall;
Return
Error Code.
Parameters
Takes a TIQStudyAutomation record.
//--------------------------------------------------------------------------------------------------
TIQStudyAutomation = record
PatientID, AccessionNo, StudyUID, SeriesUID, InstanceUID: STRING[255];
CloseCurrentStudy, AddToWindow: BOOLEAN;
SeriesRows, SeriesCols, PresentationMode: Integer;
AutoTile, AutoLoad, RemoteExam, LoadFromAllSources : BOOLEAN; ArchiveName: STRING[255];
end;
任何帮助?
答案 0 :(得分:1)
没有必要翻译记录,由于使用Delphi短串,这非常棘手。相反,您只需拨打Open_Study
即可。德尔福声明是:
function Open_Study(
PatientID: PAnsiChar;
AccessionNo: PAnsiChar;
CloseCurrentStudy: Boolean;
AddToWindow: Boolean;
SeriesRows: Integer;
SeriesCols: Integer;
PresentationMode: Integer;
AutoTile: Boolean;
AutoLoad: Boolean;
RemoteExam: Boolean
): Integer; stdcall;
翻译它的唯一真正的缺点是Delphi Boolean
类型是1字节类型。但是C#bool
默认为4字节类型的编组,以匹配Win32类型BOOL
。
所以我会像这样翻译函数:
[DllImport("Lib\\RISInterface.dll", CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi, EntryPoint = "Open_Study", ExactSpelling = true)]
static extern internal int OpenStudy(
string PatientID,
string AccessionNo,
[MarshalAs(UnmanagedType.U1)] bool CloseCurrentStudy,
[MarshalAs(UnmanagedType.U1)] bool AddToWindow,
int SeriesRows,
int SeriesCols,
int PresentationMode,
[MarshalAs(UnmanagedType.U1)] bool AutoTile,
[MarshalAs(UnmanagedType.U1)] bool AutoLoad,
[MarshalAs(UnmanagedType.U1)] bool RemoteExam
);
至于string[255]
处理起来有些棘手。该类型的大小为256.第一个字节是字符串长度,其余字节是有效负载。此有效负载是ANSI编码的8位字符的数组。此数组不需要以空值终止。
您无法自动编组,因为p / invoke框架不支持这种类型。我个人会声明将此类型翻译为byte[]
。我会用[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)]
编组。然后我会编写辅助函数来编组来自C#字符串和来自C#字符串。这些将涉及对Encoding.GetString
和Encoding.GetBytes
的调用,注意适当地处理字符串长度。
这当然是可能的,但有点凌乱。因此,我建议你尽可能避免这样做,并调用辅助函数Open_Study
。
答案 1 :(得分:0)
最终解决方案如下(结构声明,函数声明和函数将字符串转换为Delphi String [255]作为字节数组):
public struct TIQStudyAutomation
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] PatientID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] AccessionNo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] StudyUID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] SeriesUID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] InstanceUID;
[MarshalAs(UnmanagedType.U1)]
public bool CloseCurrentStudy;
[MarshalAs(UnmanagedType.U1)]
public bool AddToWindow;
public int SeriesRows;
public int SeriesCols;
public int PresentationMode;
[MarshalAs(UnmanagedType.U1)]
public bool AutoTile;
[MarshalAs(UnmanagedType.U1)]
public bool AutoLoad;
[MarshalAs(UnmanagedType.U1)]
public bool RemoteExam;
[MarshalAs(UnmanagedType.U1)]
public bool LoadFromAllSources;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public byte[] ArchiveName;
}
[DllImport("Lib\\RISInterface.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "Open_Study1", ExactSpelling = false)]
static extern internal int OpenStudy1(TIQStudyAutomation automationInfo);
private byte[] ConvertToDelphiString255(string input)
{
var output = new byte[256];
if(String.IsNullOrEmpty(input))
{
return output;
}
var ar = Encoding.ASCII.GetBytes(input);
var length = ar.Length > 255 ? 255 : ar.Length;
output[0] = (byte)length;
for(int i=0; i<length; i++)
{
output[i+1] = ar[i];
}
return output;
}