1:在DBOP_API.dll中,定义了如下的结构体和API#pragma pack(1)
struct DBOP_SNAPSHOT_TAG_VAL  //描述标签点值的相关信息的结构 
{
TAG_ID tagID;      /* 标签点的唯一ID */
TIMESTAMP timeStamp;  /* 秒级时间戳 */
unsigned short ms;      /* 毫秒 */
unsigned char tagType;     /*该标签点的值类型 */
unsigned char quality;   /* 数据质量 */
unsigned char val[1];  /* 当前值,根据标签点数据类型的不同长度不一 ,变化范围1----128 ,这里用到了越界*/
};DBOP_API int DBOP_SetSnapshotValue ( IN TAG_ID tagID, IN struct DBOP_SNAPSHOT_TAG_VAL* pVal);
DBOP_API int DBOP_GetSnapshotValue ( IN TAG_ID tagID, OUT struct DBOP_SNAPSHOT_TAG_VAL* pVal, IN int bufLen);
2:现在需要在c#下面调用:[DllImport("dbop_dll.dll", EntryPoint = "DBOP_SetSnapshotValue", CharSet = CharSet.Ansi)]
         public static extern  int DBOP_SetSnapshotValue( uint tagID,    APICommonDataStruct.DBOP_SNAPSHOT_TAG_VAL pVal);
[DllImport("dbop_dll.dll", EntryPoint = "DBOP_GetSnapshotValue", CharSet = CharSet.Ansi)]
         public static extern   int DBOP_GetSnapshotValue(uint  tagID, ref   DBOP_SNAPSHOT_TAG_VAL  pVal, int bufLen); public struct DBOP_SNAPSHOT_TAG_VAL  //描述标签点值的相关信息的结构
        {
            public uint  tagID;  /* 标签点的唯一ID */
            public uint  timeStamp;  /* 秒级时间戳 */
            public ushort ms;      /* 毫秒 */  
                
            public  byte  tagType;     /*该标签点的值类型 */
            //[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]          
            public byte   quality;   /* 数据质量 */
            [MarshalAs(UnmanagedType.ByValArray, SizeConst =128)]
            public byte [] val; /* 该标签点的值的第一个字节 */
        };
其中最后一个字节数组取的前面变长结构体的最大长度3 现在的问题是我可以读取数据,但是无法将数据写入!希望各位知道的指教啊,感激不尽!

解决方案 »

  1.   

    System.IntPtr 
    处理结构体
      

  2.   

    DBOP_API int DBOP_SetSnapshotValue ( IN TAG_ID tagID, IN struct DBOP_SNAPSHOT_TAG_VAL* pVal); 
    这里是指针[DllImport("dbop_dll.dll", EntryPoint = "DBOP_SetSnapshotValue", CharSet = CharSet.Ansi)] 
            public static extern  int DBOP_SetSnapshotValue( uint tagID,    APICommonDataStruct.DBOP_SNAPSHOT_TAG_VAL pVal); 这里却是类实例试一试加个 ref,也传指针。
    [DllImport("dbop_dll.dll", EntryPoint = "DBOP_SetSnapshotValue", CharSet = CharSet.Ansi)] 
            public static extern  int DBOP_SetSnapshotValue( uint tagID,ref    APICommonDataStruct.DBOP_SNAPSHOT_TAG_VAL pVal); 
      

  3.   

    错误:
    Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout.这个时候传入的是数据类型为整形的值,字节数为4!
      

  4.   

    System.IntPtr 这个怎么用
    找不到例子和资料
      

  5.   

    你能改C++的实现吗?DBOP_API int DBOP_SetSnapshotValue ( IN TAG_ID tagID, IN struct DBOP_SNAPSHOT_TAG_VAL* pVal); 改成DBOP_API int DBOP_SetSnapshotValue ( IN TAG_ID tagID, IN struct DBOP_SNAPSHOT_TAG_VAL& pVal); C#端不变。
      

  6.   

    msdn上的例子Platform Invoke Wrapper Example If a structure contains simple types, it can be passed to a native function. The native routine must conform to how the .NET Compact Framework packs the structure. Consider a native function called DoRequest that takes one parameter, a pointer to a structure. The structure defines two fields: A character array containing a NULL terminated ANSI string. An integer. Here is the structure in C++:   Copy Code 
    typedef struct 

        char *RequestName, 
        int  Count, 
    } ALERT_REQUEST; int DoAlertRequest(ALERT_REQUEST *pRequest); 
    Its corresponding managed version in C# is:   Copy Code 
    struct AlertRequest 

        String RequestName; 
        int    Count; 
    } class AlertClass 

        [DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest", 
            CharSet=CharacterSet.Ansi)] 
        public static extern int DoRequest(ref AlertRequest Req); 

    The DllImportAttribute attribute annotates the metadata of the native method call. It notifies the common language runtime that the DoRequest method is in ALERT.DLL, that the name of the method is DoAllertRequest, and to marshal strings to ANSI because all strings in managed code are Unicode strings. A call to this method in C++ in the .NET Framework might look like this:   Copy Code 
    AlertRequest Request = new AlertRequest() 
    Request.RequestName = "beep"; 
    Request.Count = 10; 
    AlertClass.DoRequest(ref Request); 
    When the .NET Framework's common language runtime encounters the DoRequest, call it dynamically loads ALERT.DLL, gets the address of DoAlertRequest, builds an unmanaged version of the structure converting strings as needed, pushes a pointer to this structure, and calls DoAlertRequest. It cannot just pass a pointer to the structure because it contains an embedded String object. Given these constraints, the native DoRequest method cannot be called directly. Instead, an intermediate thunking call must wrap DoRequest. The following C# code is an example:   Copy Code 
    class AlertClass 

        [DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")] 
        private static extern int DoRequestThunk(String RequestName, int Count);     public static int DoRequest(ref AlertRequst Req) 
            { 
                return DoRequestThunk(Req.RequestName, Req.Count); 
            } 

    AlertClass still contains a method with the same signature as its counterpart on the .NET Framework. The .NET Compact Framework DoRequest is a managed routine that calls a private native routine. Notice that the fields of the structure have been broken out into separate argument in the call to the native routine because the String object within the structure would not be marshaled. The thunk wraps the native DoRequest. It builds an unmanaged version of the structure and performs the string conversion, as shown here in C++:   Copy Code 
    int DoRequestThunk(wchar_t *RequestNameW, int Count) 

        ALERT_REQUEST Req; 
        int ReturnCode; 
          
        // CreateAnsiFromUnicodeString allocates and builds an ANSI 
        // version of the Unicode string. 
        Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW); 
        if (Req.RequestName == NULL) 
            Return 0;     Req.Count = Count;     // This is the native DoRequest, not to be confused 
        // with the managed method of the same name. 
        ReturnCode = DoAlertRequest(&Req);     free(Req.RequestName) 
        return ReturnCode; 

      

  7.   

    你的C++定义为:
    DBOP_API int DBOP_SetSnapshotValue ( IN TAG_ID tagID, IN struct DBOP_SNAPSHOT_TAG_VAL* pVal); 
    DBOP_API int DBOP_GetSnapshotValue ( IN TAG_ID tagID, OUT struct DBOP_SNAPSHOT_TAG_VAL* pVal, IN int bufLen); 
    所以在C#中你应定义为:
    [DllImport("dbop_dll.dll", EntryPoint = "DBOP_SetSnapshotValue", CharSet = CharSet.Ansi)] 
    public static extern  int DBOP_SetSnapshotValue( uint tagID,  ref APICommonDataStruct.DBOP_SNAPSHOT_TAG_VAL pVal); 
    [DllImport("dbop_dll.dll", EntryPoint = "DBOP_GetSnapshotValue", CharSet = CharSet.Ansi)] 
    public static extern  int DBOP_GetSnapshotValue(uint  tagID, ref  DBOP_SNAPSHOT_TAG_VAL  pVal, int bufLen); 
      

  8.   

    没用的
    加个ref还是前面的错误
      

  9.   

    直接在C#中用unsafe一包,然后用指针吧。