在c#中声明指针以指向c dll中的非托管结构

在c#中声明指针以指向c dll中的非托管结构,c#,C#,有一个问题我已经两天没能解决了 错误消息如下所示: [StructLayout(LayoutKind.Sequential)] unsafe public struct PHOTONIQ_CONFIG_TABLE { [MarshalAs(UnmanagedType.U2)] public UInt16 SystemMode; //Indicates current system mode

有一个问题我已经两天没能解决了

错误消息如下所示:

        [StructLayout(LayoutKind.Sequential)]
        unsafe public struct PHOTONIQ_CONFIG_TABLE
        {
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SystemMode;       //Indicates current system mode, acquire or standby mode 0 = Standby Mode 1 = Acquire Mode
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 HVLimit0;   // Maximum allowed voltage on HV supply 1 Range = 500 ?9250 (50 ?925V)
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 HVLimit1;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 NumChannelsB0;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 NumChannelsB1;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 NumChannelsB2;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 NumChannelsB3;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 HVEnabled;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 HVSetpoint0;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 HVSetpoint1;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 UserConfigID;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 DCRD_AOut_0;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 BandEnables;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band0StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band0StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band1StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band1StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band2StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band2StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band3StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band3StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band4StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band4StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band5StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band5StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band6StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band6StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band7StartIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 Band7StopIndex;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 FlagEnables;      // pterm flag enables
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag0Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag1Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag2Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag3Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag4Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag5Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag6Operands[4];   // flag 0 operands: 64 bits
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 Flag7Operands[4];   // flag 0 operands: 64 bits
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm0;               // flag 0 - 7 product terms
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm1;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm2;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm3;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm4;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm5;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm6;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 PTerm7;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 DataFilterEnable; // 1 = enable spectral filtering, 0 = disable
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 ProcessingEnables;    // bit 0 = spect filt, bit 1 = gain, 2 = bkgnd sub.
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 TimestampEnable;  // 1 = enable time stamp, 0 = disable
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 DACspare;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 TimestampInterval; //
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 CustomWordsEnable;    // 1/0
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 EventCustomCount; //
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 RESERVED;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 ImageAcqMode;     // 1 = image, 0 = particle
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 InputTrigThresh;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 InputTrigChannel; // 
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 RangeErrorEnable; // 1 = enable range error, 0 = disable
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 CrossBankConfig;  //
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 ReportPackingMode;    //
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 GPOutputEnable;       //
            [MarshalAs(UnmanagedType.I4)]
            public Int32 GPOutputDelay;     //
            [MarshalAs(UnmanagedType.I4)]
            public Int32 GPOutputPeriod;        //
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 IntBoxcarEnable;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 BoxcarWidthEnable;
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed Int32 ResetDelay[4];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 TrigSource[4];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed Int32 TrigPeriod[4];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed Int32 IntegPeriod[4];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed Int32 IntegDelay[4];
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel0;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel1;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel2;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel3;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel4;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel5;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel6;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 SibSel7;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 TriggerEndCount;
            [MarshalAs(UnmanagedType.U2)]
            public UInt16 TrigStampSelect;
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
            public fixed UInt16 DataFormat[4];      // 4 banks: 0 = 17bit sign/mag, 1 = 16bit 2's, comp, 2 = 16b, 2's 1/2 scale
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 7)]
            public fixed UInt16 RESERVED1[7];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
            public fixed UInt16 GainArray[256];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 256)]
            public fixed UInt16 TrigThreshArray[256];
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16)]
            public fixed UInt16 TrigEnableArray[16];    // 256 bits, 1/0 for each channel (max of 256 channels)
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 322)]
            public fixed UInt16 RESERVED2[322];         //  678-999
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 250)]
            public fixed UInt16 CustomArray[250];           // user custom space: 1000-1249
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 567)]
            public fixed UInt16 FactoryArray[567];          // start of factory table
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32)]
            public fixed SByte ModelNumber[32];         // model number
            //[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 151)]
            public fixed UInt16 FactoryArray1[151];
            //public fixed UInt16 FactoryArray1[151];       // last piece of factory table
        };  
无法获取托管类型的地址、大小或声明指向托管类型的指针 ('Control_Vertilon.Imports.PHOTONIQ_CONFIG_TABLE')

下面是代码

         UInt16[] Arguments = new UInt16[PHOTONIQ_ARG_BUFF_SZ];

         PHOTONIQ_CONFIG_TABLE PhotoniqConfigTable = new PHOTONIQ_CONFIG_TABLE();

        UInt16 *cfgPtr = (UInt16*)&PhotoniqConfigTable;       

        for(int i = 0; i < Imports.CONFIG_TABLE_SZ; i++){
            Arguments[i+1] =  *cfgPtr++; 
        }

        Imports.ControlInterface(Opcode, Arguments, 0x1, Imports.TimeoutMs, ref errInNoErrorStruct, ref NumRetArguments, ref PhotoniqConfigTable, Imports.CONFIG_TABLE_SZ, ref errOutStruct);   
问题是,我以为我把结构设为非托管类型,但编译器却说它是托管类型

或者,在托管代码中,指向这种方式的UInt16指针可能是错误的

缓冲区参数[]是16位的,这是dll函数中的传递参数,因此无论是用作指针还是用作缓冲区来移动数据,我都坚持使用16位

如果有人能帮助解决这个问题,那将是一个巨大的帮助

我在网上搜索了一下,却找不到确切的答案

提前谢谢

==================================================================================

嗨,谢谢你的回复

在这里,我收到不同的错误,代码如下:

        fixed (UInt16 *cfgPtr = (UInt16*)&PhotoniqConfigTable){
            //modify config table, then send it back up to PhotoniQ
            PhotoniqConfigTable.NumChannelsB0 = 6;
            PhotoniqConfigTable.IntegPeriod[0] = per;
            PhotoniqConfigTable.TrigPeriod[0] = 100000;
            PhotoniqConfigTable.TrigStampSelect = 1;
            PhotoniqConfigTable.TimestampEnable = 0;
            PhotoniqConfigTable.RangeErrorEnable = 0;
            PhotoniqConfigTable.DataFormat[0] = 0;
            PhotoniqConfigTable.GPOutputEnable = 1;
            PhotoniqConfigTable.GPOutputDelay = 10;
            PhotoniqConfigTable.GPOutputPeriod = 1000;

            for (int i = 0; i < Imports.CONFIG_TABLE_SZ; i++)
            {
                Arguments[i + 1] = *cfgPtr++;
            }
        }      

您已经提到了阵列在非托管内存中的布局方式,但没有提到它们在托管内存中的布局方式。因此,编译器认为您在该结构(所有这些数组)中有一堆对垃圾收集托管内存的引用,因此不允许您获取指向它的指针

我怀疑您打算让这些阵列成为固定大小的缓冲区,而不是托管阵列,是吗

您需要阅读C#规范第18.7节,以了解固定大小缓冲区在结构中的工作方式


还注意到;这是“固定”一词的两种完全不同的用法。许多人对此感到困惑,特别是因为要正确、安全地使用“固定大小”的缓冲区,缓冲区的内存必须“固定到位”

您已经提到了阵列在非托管内存中的布局,但没有提到它们在托管内存中的布局。因此,编译器认为您在该结构(所有这些数组)中有一堆对垃圾收集托管内存的引用,因此不允许您获取指向它的指针

我怀疑您打算让这些阵列成为固定大小的缓冲区,而不是托管阵列,是吗

您需要阅读C#规范第18.7节,以了解固定大小缓冲区在结构中的工作方式

还注意到;这是“固定”一词的两种完全不同的用法。许多人对此感到困惑,特别是因为要正确、安全地使用“固定大小”的缓冲区,缓冲区的内存必须“固定到位”

而不是

        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 151)]
        public UInt16[] FactoryArray1;

因为阵列在托管内存和非托管内存中“外观”不同,但固定大小的缓冲区“外观”相同(即,可快速删除)。

而不是

        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 151)]
        public UInt16[] FactoryArray1;


因为阵列在托管内存和非托管内存中“外观”不同,但固定大小的缓冲区“外观”相同(即,可快速删除)。

第二个答案,回答第二个问题:

错误消息如下:

错误消息会告诉您出了什么问题。阅读它们。

无法分配给“cfgPtr”,因为它是“固定变量”

您将在此处为其分配:

Arguments[i + 1] = *cfgPtr++;
初始化包含指向固定内空间块的指针的变量后,无法更改该变量,因为可能会将其更改为指向非固定内空间块。为了防止这种常见的错误,C#会阻止您修改该变量

如果要修改变量,请改为创建其他变量。将其设置为等于
cfgPtr
,然后修改该变量。确保你做得正确;您现在负责确保指针指向已修复的对象

The right hand side of a fixed statement assignment may not be a cast expression.
在我的最后一个回答中,我告诉您阅读规范的第18.7节,其中规定“固定”语句需要:

引用可移动变量的固定大小缓冲区成员的简单名称或成员访问

强制转换表达式不是“简单名称或成员访问”。强制转换表达式是强制转换表达式。这个演员阵容根本没有意义!指向结构的指针不是指向ushort的指针

取下铸件。将初始值设定项中的表达式更改为访问可移动变量的固定大小缓冲区成员的成员

You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
您直接使用固定大小的缓冲区您不能这样做。您只能通过获取指向固定大小缓冲区的指针来使用该缓冲区。同样,这是安全系统的一部分,可确保您不会意外访问未固定到位的固定大小缓冲区。停止尝试直接访问缓冲区。获取指向缓冲区的指针并通过该指针访问它

任何能向我解释的人都会帮上大忙,因为我时间不多

让我非常清楚地说明这一点:您已经关闭了托管安全系统,程序的正确性和进程的稳定性现在是您的问题,而不是托管运行时的问题。如果您不了解如何安全地管理自己的指针,停止你正在做的事情,仔细阅读,直到你明白为止。现在仓促行事,编写了大量您不理解的代码,这意味着您有可能不得不在以后处理可怕的bug。现在不是匆忙的时候


从阅读第18章开始。只有当你彻底理解了所有这些内容后,你才应该尝试编写复杂的不安全代码。

第二个答案,来回答你的第二个问题:

错误消息如下:

错误消息会告诉您出了什么问题。阅读它们。

无法分配给“cfgPtr”,因为它是“固定变量”

您将在此处为其分配:

Arguments[i + 1] = *cfgPtr++;
初始化包含指向固定空间块指针的变量后,无法更改
You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.