C# 调用需要双精度数组和结构作为输入的 C++ DLL 函数
Posted
技术标签:
【中文标题】C# 调用需要双精度数组和结构作为输入的 C++ DLL 函数【英文标题】:C# call to C++ DLL function that requires an array of doubles and a struct as input 【发布时间】:2017-12-17 11:15:21 【问题描述】:我需要在我的 C# 代码中从旧的 C++ DLL 调用以下函数。我无法编辑 C++ 代码,这就是我掌握的关于该函数的所有信息:
LoadMemDouble:
函数:uint PASCAL LoadMemDoubleAB(void far* lpobj,double far* lpy,TARHDR far* lptar)
目的:将数据从传递的 64 位结构加载到 DLL 浮动。重要 - 任何传递的数组、数据结构等必须是 全局,因为 DLL 只维护一个指向数组/结构的指针。
参数:
lpobj = 预测数据结构的远指针;
lpy = double 类型 y 值的指针;
lptar = 数据头指针。注意 TARHDR 被定义为:
typedef struct dword tarnpts; //total number of data
double tarffp; //x value of first y data
double tarflp; //x value of last y data
char tarxtype; //data type of x value
char tarytype; //data type of y value
uint tarx; //1=has x value 0=only y trace
TARHDR;
!!tarx 字段必须设置为零;
返回:0 或错误代码。
我在 C# 中导入的 DLL 如下:
[DllImport("plsiqp32.dll", EntryPoint = "LoadMemDouble", SetLastError = true, CharSet = CharSet.None)]
public static extern int dLoadMemDouble(int handleCal, ref double dYvalues, ref DoubleHeader Header);
我在 C# 中构建了如下结构:
public struct DoubleHeader
public int npts get; set;
public double FFP get; set;
public double FLP get; set;
public byte Xtype get; set;
public byte YType get; set;
public int Xtra get; set; //this must be 0.
然后:
public DoubleHeader myHeader;
public double[] myYvalues;
myHeader = new DoubleHeader();
myHeader.npts = npts;
myHeader.FFP = FFP;
myHeader.FLP = FLP;
myHeader.XType= Xtype;
myHeader.YType = Ytype;
myHeader.Xtra = 0;
myYvalues = dYvalues;
int loadFromMemory;
loadFromMemory = dLoadMemDouble(handleCal, ref myYvalues[0], ref myHeader);
我没有任何类型的错误消息,但它似乎无法正常工作。我怀疑我传递双精度数组和/或结构的方式存在错误。我对 C# 也很陌生,我被这个问题困住了。
我能找到的只有德语的信息:http://microsoft.public.de.german.entwickler.dotnet.csharp.narkive.com/g9rTQP1U/c-dll-in-c-nutzen#post9 它的历史可以追溯到 14 年前...这是一个非常古老的 DLL。
感谢您的帮助!
【问题讨论】:
我的函数使用Windows参数列表还是C语言参数列表?我会在 c# 中使用 IntPtr 作为指针。 IntPtr 是 4 个字节,相当于 c# Int 代码可能看起来像是在工作。我还会将返回参数设为 uint 而不是 int,以便与 dll 相同。 【参考方案1】:是的,正如 jdweng 建议的那样,解决方案是在 C# 中为 dMemDouble 使用 IntPtr。 如下:
[DllImport("plsiqp32.dll", EntryPoint = "LoadMemDouble", SetLastError = true, CharSet = CharSet.None)]
public static extern uint dLoadMemDouble(int handleCal, IntPtr dYvalues, ref DoubleHeader Header);
然后:
IntPtr p = Marshal.AllocCoTaskMem(sizeof(double) * myYvalues.Length);
Marshal.Copy(myYvalues, 0, p, myYvalues.Length);
loadFromMemory = dLoadMemDouble(handleCal, p, ref myHeader);
Marshal.FreeHGlobal(p);
现在效果很好。 谢谢!
【讨论】:
以上是关于C# 调用需要双精度数组和结构作为输入的 C++ DLL 函数的主要内容,如果未能解决你的问题,请参考以下文章
从输入中获取数字和单位作为双精度和字符串 - 编程:使用 C++ 的原则和实践