猿问

如何从C#使用结构指针参数调用C ++函数?

好的,还有一个功能,它还没有工作。我基本上是通过使用P / Invoke从C#调用一些C ++函数的。有问题的功能确实会向演出激光设备查询一些与设备有关的信息,例如最小和最大扫描速率以及每秒最大点数。


有问题的功能是:


int GetDeviceInfo(DWORD deviceIndex, DeviceInfo* pDeviceInfo);

这是我得到的C ++头文件。这是非常简短的C ++ SDK描述的链接。我没有重建DLL文件的源,也没有* .pdb文件(制造商无法提供):


#pragma once


#ifdef STCL_DEVICES_DLL

#define STCL_DEVICES_EXPORT extern "C" _declspec(dllexport) 

#else

#define STCL_DEVICES_EXPORT extern "C" _declspec(dllimport)

#endif


enum SD_ERR

{

    SD_ERR_OK = 0,

    SD_ERR_FAIL,

    SD_ERR_DLL_NOT_OPEN,

    SD_ERR_INVALID_DEVICE,  //device with such index doesn't exist

    SD_ERR_FRAME_NOT_SENT,

};


#pragma pack (1)

struct LaserPoint

{

    WORD x;

    WORD y;

    byte colors[6];

};


struct DeviceInfo

{

    DWORD maxScanrate;

    DWORD minScanrate;

    DWORD maxNumOfPoints;

    char type[32];

};



这是我当前正在使用的完整C#测试代码。除以下功能外,所有功能均正常运行

第64行(cp屏幕截图):


int r4 = GetDeviceInfo(0, ref pDevInfo); 

我收到以下错误:


An unhandled exception of type 'System.NullReferenceException' occured in MonchaTestSDK.exe

Additional information: Object reference not set to an instance of an object

这是堆栈跟踪(如果没有DLL的* .pdb文件,就无法提供更好的堆栈跟踪):

MonchaTestSDK.exe!MonchaTestSDK.Program.Main(string [] args)第73行+ 0xa字节C#mscoreei.dll!73a8d91b()

[下面的帧可能不正确和/或丢失,没有为mscoreei.dll加载任何符号]

mscoree.dll !73cae879()

mscoree.dll!73cb4df8()

kernel32.dll!74a08654()

ntdll.dll!77354b17()

ntdll.dll!77354ae7()


一些拆卸:


            int r4 = GetDeviceInfo(0, ref pDevInfo);

05210749  int         3  

0521074A  push        ebp  

0521074B  cwde  

0521074C  xor         ecx,ecx  

0521074E  call        0521011C  

05210753  int         3  

05210754  test        dword ptr [eax-1],edx  

05210757  ?? ?? 

05210758  dec         dword ptr [ebx-0AF7Bh]  

0521075E  dec         dword ptr [ecx-6F466BBBh]

知道我在这里做错了吗?


GCT1015
浏览 229回答 3
3回答

ABOUTYOU

正确的应该是string UnpackFixed(byte[] data, System.Text.Encoding encoding){    int i;    for (i = 0; i < data.Length; ++i)        if(data[i] == (byte)0)            break;    return encoding.GetString(data, i);}[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]struct DeviceInfo{    uint32 maxScanrate;    uint32 minScanrate;    uint32 maxNumOfPoints;    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]    byte type[];};DeviceInfo pDevInfo = new DeviceInfo();pDevInfo.type = new byte[32];int r4 = GetDeviceInfo(0, ref pDevInfo);Console.WriteLine("  - type: " + UnpackFixed(pDevInfo.type));我敢肯定有一种方法可以做到这一点,string但是所有古老的显而易见的方法都倾向于将字符串传递给本机代码,并且什么也得不到。在这里,练习是找回固定长度的字节字符串。如果确实为字符串解决了问题,那么最终将使用System.Text.Encoding.Default正确或不正确的字符串,并且没有任何方法可以覆盖它。System.Text.Encoding.ASCII可能是错误的,在这种情况下,您需要处理编码。System.Text.Encoding.Default也许可以在ASCII不工作的地方工作,在这种情况下,您应该考虑在多字节字符编码上是否有奇怪的失败模式。目前尚不清楚设备是始终使用与操作系统相同的编码,还是采用固定编码(在这种情况下,您应指定编码)。
随时随地看视频慕课网APP
我要回答