我/我们目前有一个用Delphi(XE,特别是)编写的程序,它与一个非托管DLL(用C++编写,从我所听到的)接口。 Delphi应用程序正在退役,但需要与非托管DLL一起工作,所以需要编写一个C#接口。没什么大不了。除了没有访问DLL的源代码或任何有关它的良好文档,以及这是我第一次进入互操作性,正在杀死我。将Delphi非COM DLL接口转换为C#
这里是在DLL中可使用功能的文档:
extern EXTERNC __declspec(dllexport) long initiate (
double conc1,
double conc2,
long temp,
const char* NT
);
extern EXTERNC __declspec(dllexport) long DoWork (
long NumItems,
struct Structure* Items
);
在Delphi中,这些都是成功地实施这样的(与自定义结构也包括在内):
function CustomInitialize
(
Concentration1 : double;
Concentration2 : double;
Temperature : LongInt;
const Type : PAnsiChar
) : LongInt; cdecl; external 'CustomDLL.dll' name '_initiate';
procedure DoWork
(
NumItems : LongInt;
Items : PStructure
); cdecl; external 'CustomDLL.dll' name '_DoWork';
TStructure = record
ValueName : PAnsiChar;
Value : PAnsiChar;
Status : LongInt;
ReturnVal1 : Double;
ReturnVal2 : Double;
ReturnVal3 : Double;
Temp : Double;
end;
PStructure = ^TStructure;
注意的是,虽然DoWork方法似乎需要一系列项目,所有实现都将NumItems设置为1,并在Delphi中循环遍历对象,而不是将其传递给C++。
在C#中,我甚至不知道应该发布哪个示例。我已经搜索了好几天,试着让我觉得每个版本的代码都可以尝试,但都无济于事。这是最新版本:
namespace JunkProject
{
class Program
{
static void Main(string[] args)
{
int test = _initiate(.05, .05, 60, "1");
Console.WriteLine(test);
if (test != 1)
Console.ReadLine();
var structure = new FoldStructure() { ValueName = "Test1", Value = "TESTTESTTESTTESTTESTTESTTEST", Status = 0, ReturnVal1 = 0.0, ReturnVal2 = 0.0, ReturnVal3 = 0.0, Temp = 0.0 };
test = _DoWork(1, structure);
Console.WriteLine(structure.Value);
Console.ReadLine();
}
private const string DLL_LOCATION = "CustomDLL.dll";
[DllImport(DLL_LOCATION, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int _initiate(double Conc1, double Conc2, int Temp, [MarshalAs(UnmanagedType.LPStr, SizeConst = 5)] string Type);
[DllImport(DLL_LOCATION, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int _DoWork(int NumItems, [In, Out] Structure Struct);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class Structure
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
public string ValueName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 28)]
public string Value;
public int Status;
public double ReturnVal1;
public double ReturnVal2;
public double ReturnVal3;
public double Temp;
}
}
}
但是,这样做会导致访问冲突。我已经尝试使方法签名为IntPtr,但失败。我试图让方法签名成为一个指向struct的指针,在我尝试的每种方式中,这通常都会出现可怕的错误,尽管我无法确定我是否已经很长时间地以“正确的方式”因为我不确定那是怎么回事。我想如果我能弄清楚正确的方法签名是什么,那将会有好处。
此外,道歉轻微混淆来源。我正在使用的DLL是专有和whatnot。
任何帮助先行感谢!
谢谢!数组的概念是我早些时候尝试过的,但是我对我实际上在做什么的理解仍然是绿色的,所以我可能只是错了。这些评论绝对有意义,有助于澄清我错过的东西。我确实在每一个这样的事情上来回奔走,但我陷入了一种“反复的”编程梦魇,没有反馈机制,看看有没有更好的工作。 –