从C ++ DLL到C#项目读取复杂的结构 [英] Reading a complex struct from C++ DLL to C# project

查看:74
本文介绍了从C ++ DLL到C#项目读取复杂的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问候。



我正在研究扫描仪管理项目。 Provider向我发送了.dll和.h文件(C ++ native),因为我需要构建一个包装器来在我的C#项目中使用它。有些函数没有问题,但是其他函数实际上很难调用(或者至少我没有这样做的经验)。



其中一个涉及指向在内部有其他结构。



这是C ++中的代码



Greetings.

I'm working on a scanner management project. Provider sent me the .dll and .h files (C++ native) for I need to build a wrapper to use it in my C# project. Some functions had no problems, but others are really difficult to invoke (or at least I dont have enought experience for doing that).

One of them involves a pointer to struck, that internally has other structs.

This is the code in C++

typedef struct _ImParam
{
  UINT Format;
  UINT Resolution;
  UINT ColorDepth;
} IM_PARAM;

typedef struct _sValues
{
  UINT Xpos;
  UINT Ypos;
  UINT Width;
  UINT Height;
  BOOL Milli; 
} S_VALUES;

typedef struct _sProperties
{
  BOOL Enable;
  S_VALUES Properties;
} S_PROPERTIES;

typedef struct _DevParam
{
  BOOL Enable;
  UINT Font;
  char Symbol;
  IM_PARAM Image1;
  IM_PARAM Image2;
  S_PROPERTIES Properties[10];
  UINT FeedMode;
} DevParam;

// more code, comments, etc. etc.

// The function I want to use
BOOL GetParameters( DWORD ID, DevParam  *dParam );





这就是我在C#中定义结构的方式





and this is how I defined the structs in C#

[StructLayout(LayoutKind.Sequential)]
public struct ImParam
{
   public uint Format;
   public uint Resolution;
   public uint ColorDepth;

   public ImParam(uint n)
   {
       Format = n;
       Resolution = 300;
       ColorDepth = 256;
   }
};

[StructLayout(LayoutKind.Sequential)]
public struct sValues
{
   public uint Xpos;
   public uint Ypos;
   public uint Width;
   public uint Height;
   [MarshalAs(UnmanagedType.Bool)]
   public bool Milli;

   public sValues(uint n)
   {
       Xpos = n;
       Ypos = n;
       Width = n;
       Height = n;
       Milli = false;
   }
};

[StructLayout(LayoutKind.Sequential)]
public struct sProperties
{
   [MarshalAs(UnmanagedType.Bool)]
   public bool Enable;
   public sValues Properties;

   public sProperties(int n)
   {
       Enable = false;
       Properties = new sValues(n);
   }
};

[StructLayout(LayoutKind.Sequential)]
public struct DevParam
{
   [MarshalAs(UnmanagedType.Bool)]
   public bool Enable;
   public uint Font;
   public char Symbol;
   public ImParam Image1;
   public ImParam Image2;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
   public sProperties[] Properties;
   public uint FeedMode;

   public DeviceParameters(int n)
   {
       Enable = true;
       Font = 0;
       Symbol = '?';
       Image1 = new ImParam(3);
       Image2 = new ImParam(3);
       Properties = new sProperties[10];
       for(int i = 0; i < 10; i++)
          Properties[i] = new sProperties(n);
       FeedMode = 1;
   }
};





我需要的是从C ++中获取结构。



我尝试了什么:



我尝试在结构中添加引用





What I need is to get the struct from the C++.

What I have tried:

I tried adding a ref to the struct

// At the wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, out DevParam dParam);

// At main
DevParam DP; // Got ID previously
bool res = Class1.GetParameters(ID, out DP);
Console.WriteLine("Result: " + res);





也尝试使用IntPtr





Also tried using an IntPtr

// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, ref IntPtr dParam);

// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, ref Ptr);
Console.WriteLine("Result: " + res);
var test = Marshal.PtrToStructure(Ptr, typeof(DevParam));
// No idea what I'll do here
Marshal.FreeHGlobal(Ptr);





在这两种情况下,结果res为真(意味着函数被正确调用)但我没有得到结构。使用第一个解决方案,struct成员具有默认值(所有0都带有数字,所有false都带有bool),而第二个解决方案,Ptr为0,这意味着没有得到正确的内存地址。



有什么帮助吗?已经工作了好几周了,我已经完全卡住了。



注意:没有.dll的源代码

注2:没有足够的dll导入经验。对于傻瓜来说这将是一个很好的解释

注3:对于这么长的帖子很抱歉



In both cases the result "res" is true (means function was called correctly) but I'm not getting the struct. With the first solution the struct members have default values (all 0 with numbers, all false with bool), and with the second one, Ptr is 0, that means didn't get a correct memory address.

Any help? Been working in this for weeks already and I'm completely stuck.

Note: Don't have source code of the .dll
Note2: Don't have enough experience with dll imports. Would be good an explanation "for dummies"
Note3: Sorry for such a long post

推荐答案

我的代码中没有看到任何地方你在哪里调用GetParameters()函数。此外,你需要知道入口点的确切名称,mangledFunction听起来不对(我不是C#guru)。如果您没有DLL的源代码并且它使用C ++修改,您可以使用DEPENDS.EXE工具查找确切的入口点名称拼写
I do not see anywhere in your code where you calling GetParameters() function. Also you need to know the exact name of the entry point and "mangledFunction" does not sound right (I am not a C# guru though). if you do not have the source code for the DLL and if it uses C++ mangling, you can use "DEPENDS.EXE" tool to lookup exact entry point name spelling


以下是解决方案:



Here comes the solution:

// At the dll wrapper class
[DllImport(path, EntryPoint = "?GetParameters@@YGHKPAU_DevParam@@@Z")]
public static extern bool GetParameters(int ID, IntPtr dParam);

// At main
int size = Marshal.SizeOf(typeof(DevParam));
IntPtr Ptr = Marshal.AllocHGlobal(size);
bool res = Class1.GetParameters(ID, Ptr);
DevParam test = (DevParam)Marshal.PtrToStructure(Ptr, typeof(DevParam));

// For testing purpoises, previously changed the default values with another method
Console.WriteLine(test.Enable);

Marshal.FreeHGlobal(Ptr);





谢谢!



Thank you!


这篇关于从C ++ DLL到C#项目读取复杂的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆