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,以便与 d​​ll 相同。 【参考方案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++ 的原则和实践

将 C# 类库导入 Visual C++

PInvoke:返回的双精度数组有问题吗?

C#和C++传递结构体

在 C# 中使用非托管 C++ 代码对所有双精度类型返回 0

C#调用C++的dll库怎么传递结构体中不定长度的char数组