我有一个从C ++非托管库开始生成C#包装器的问题。每次我陷入System.AccessViolationException:尝试读取或写入受保护的内存。我知道这可能取决于我将结构及其元素从C ++转换为C#的方式,但我不知道如何解决。 有人能帮助我吗?
C ++代码:
typedef struct VBLEnvironmentVariable_t
{
VBLObjectHeader mHeader;
DWORD mNameLength;
DWORD mDataLength;
LPSTR mName;
LPBYTE mData;
} VBLEnvironmentVariable;
typedef struct VBLAppTrigger_t
{
VBLObjectHeader mHeader;
ULONGLONG mPreTriggerTime;
ULONGLONG mPostTriggerTime;
WORD mChannel;
WORD mFlags;
DWORD mAppSecific2;
} VBLAppTrigger;
//signature
BLAPI( BOOL) BLWriteObject( HANDLE hFile, VBLObjectHeaderBase* pBase);
//how function is called
int write_test( LPCTSTR pFileName, LPDWORD pWritten)
{
if ( NULL == pWritten)
{
return -1;
}
*pWritten = 0;
/* open file */
hFile = BLCreateFile( pFileName, GENERIC_WRITE);
if ( INVALID_HANDLE_VALUE == hFile)
{
return -1;
}
/* set applicaton information */
/* bSuccess = BLSetApplication( hFile, BL_APPID_UNKNOWN, 1, 0, 0); */
bSuccess = BLSetApplication( hFile, BL_APPID_CANCASEXLLOG, 1, 0, 1);
GetSystemTime( &systemTime);
bSuccess = bSuccess && BLSetMeasurementStartTime( hFile, &systemTime);
/* set write options */
bSuccess = bSuccess && BLSetWriteOptions( hFile, 6, 0);
if ( bSuccess)
{
// setup object headers
appTrigger.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
appTrigger.mHeader.mBase.mHeaderSize = sizeof( appTrigger.mHeader);
appTrigger.mHeader.mBase.mHeaderVersion = 1;
appTrigger.mHeader.mBase.mObjectSize = sizeof( VBLAppTrigger);
appTrigger.mHeader.mBase.mObjectType = BL_OBJ_TYPE_APP_TRIGGER;
appTrigger.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
message.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
message.mHeader.mBase.mHeaderSize = sizeof( message.mHeader);
message.mHeader.mBase.mHeaderVersion = 1;
message.mHeader.mBase.mObjectSize = sizeof( VBLCANMessage);
message.mHeader.mBase.mObjectType = BL_OBJ_TYPE_CAN_MESSAGE;
message.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
variable_s.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
variable_s.mHeader.mBase.mHeaderSize = sizeof( variable_s.mHeader);
variable_s.mHeader.mBase.mHeaderVersion = 1;
variable_s.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ENV_STRING;
variable_s.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
variable_i.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
variable_i.mHeader.mBase.mHeaderSize = sizeof( variable_i.mHeader);
variable_i.mHeader.mBase.mHeaderVersion = 1;
variable_i.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ENV_INTEGER;
variable_i.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
ethframe.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
ethframe.mHeader.mBase.mHeaderSize = sizeof( ethframe.mHeader);
ethframe.mHeader.mBase.mHeaderVersion = 1;
ethframe.mHeader.mBase.mObjectType = BL_OBJ_TYPE_ETHERNET_FRAME;
ethframe.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
appText.mHeader.mBase.mSignature = BL_OBJ_SIGNATURE;
appText.mHeader.mBase.mHeaderSize = sizeof( appText.mHeader);
appText.mHeader.mBase.mHeaderVersion = 1;
appText.mHeader.mBase.mObjectType = BL_OBJ_TYPE_APP_TEXT;
appText.mHeader.mObjectFlags = BL_OBJ_FLAG_TIME_ONE_NANS;
for ( i = 0; i < 1000; ++i)
{
ethbuffer[i] = ( BYTE)i;
}
for ( i = 0; i < 1000 && bSuccess; ++i)
{
// increment in milliseconds
time = i * 10000000;
// setup app trigger object header
appTrigger.mHeader.mObjectTimeStamp = time;
// write app trigger object
bSuccess = BLWriteObject( hFile, &appTrigger.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
// setup CAN object header
message.mHeader.mObjectTimeStamp = time;
// setup CAN message
message.mChannel = 1;
message.mFlags = CAN_MSG_FLAGS( 0, 0);
message.mDLC = 8;
message.mID = 0x100;
memcpy( message.mData, ( i % 2) ? _T( "01234567") : _T( "76543210"), message.mDLC);
// write CAN message
bSuccess = BLWriteObject( hFile, &message.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
if ( 0 == ( i % 3) && bSuccess)
{
// setup environment variable object headers
variable_s.mHeader.mObjectTimeStamp = time;
variable_i.mHeader.mObjectTimeStamp = time;
// setup environment variables
variable_s.mNameLength = strlen( ENV_NAME1);
variable_s.mDataLength = strlen( ( i % 2) ? ENV_DATA1 : ENV_DATA2);
variable_s.mName = ENV_NAME1;
variable_s.mData = ( i % 2) ? ENV_DATA1 : ENV_DATA2;
variable_s.mHeader.mBase.mObjectSize = sizeof( VBLEnvironmentVariable) + variable_s.mNameLength + variable_s.mDataLength;
variable_i.mNameLength = strlen( ENV_NAME2);
variable_i.mDataLength = sizeof( int);
variable_i.mName = ENV_NAME2;
variable_i.mData = ( LPBYTE)&i;
variable_i.mHeader.mBase.mObjectSize = sizeof( VBLEnvironmentVariable) + variable_i.mNameLength + variable_i.mDataLength;
// write environment variables
bSuccess = BLWriteObject( hFile, &variable_s.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
bSuccess = bSuccess && BLWriteObject( hFile, &variable_i.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
// write ethernet frame
memcpy( ethframe.mSourceAddress, src, sizeof( ethframe.mSourceAddress));
ethframe.mReserved1 = 0;
memcpy( ethframe.mDestinationAddress, dst, sizeof( ethframe.mDestinationAddress));
ethframe.mReserved2 = 0;
ethframe.mType = 0x0800;
ethframe.mTPID = 0;
ethframe.mTCI = 0;
ethframe.mPayLoadLength = ( WORD)i;
ethframe.mPayLoad = ethbuffer;
ethframe.mHeader.mBase.mObjectSize = sizeof( VBLEthernetFrame) + ethframe.mPayLoadLength;
bSuccess = bSuccess && BLWriteObject( hFile, ðframe.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
// write text
if ( ( i % 100) == 0)
{
char text[128];
sprintf( text, "%d objects written...", *pWritten);
appText.mText = text;
appText.mTextLength = strlen( appText.mText);
appText.mHeader.mBase.mObjectSize = sizeof( VBLAppText) + appText.mTextLength;
bSuccess = bSuccess && BLWriteObject( hFile, &appText.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
}
}
}
appText.mText = "All objects written...";
appText.mTextLength = strlen( appText.mText);
appText.mHeader.mBase.mObjectSize = sizeof( VBLAppText) + appText.mTextLength;
bSuccess = bSuccess && BLWriteObject( hFile, &appText.mHeader.mBase);
*pWritten += bSuccess ? 1 : 0;
}
/* close file */
if ( !BLCloseHandle( hFile))
{
return -1;
}
return bSuccess ? 0 : -1;
}`
C#代码:
//translation of C++ struct into C# class
public class VBLEnvVar
{
public VBLEnvVarStruct variable_s;
public VBLEnvVar()
{
variable_s = new BLF_Function.VBLEnvVar.VBLEnvVarStruct();
}
public struct VBLEnvVarStruct
{
public VBLObjectHeader.VBLObjectHeaderStruct mHeader;
public uint NameLength;
public uint DataLength;
public string Name;
[MarshalAsAttribute(UnmanagedType.LPArray)]
public byte[] Data;
}
}
public class VBLAppTrigger
{
public VBLAppTriggerStruct apptrigger;
public VBLAppTrigger()
{
apptrigger = new BLF_Function.VBLAppTrigger.VBLAppTriggerStruct(null);
}
public struct VBLAppTriggerStruct
{
public VBLObjectHeader.VBLObjectHeaderStruct mHeader;
public UInt64 mPreTriggerTime;
public UInt64 mPostTriggerTime;
public ushort mFlags;
public ushort mChannel;
public uint mAppSpecific2;
}
}
[DllImport("binlog.dll")]
public static extern bool BLWriteObject( int Handle,ref BLF_Function.ObjectHeader.ObjHeader pBase);
//how function is called into C# code
public static void Main(string[] args)
{
int written=0;
BLF_Function b = new BLF_Function();
UInt64 time=0;
byte[] ethbuffer = new byte[1500];
bool success=false;
string filename = "provamia.blf";
int Handle = MyBLF.BLCreateFile(filename,b.GENERIC_WRITE);
if (Handle != -1)
{
success = MyBLF.BLSetApplication( Handle, (byte)BLF_Function.FileStatistics.APPID.BL_APPID_UNKNOWN, 1, 0, 1);
//***********
MyBLF.SYSTEMTIME d = new MyBLF.SYSTEMTIME();
MyBLF.GetLocalTime(out d);
MyBLF.SYSTEMTIME* s = &d;
success = MyBLF.BLSetMeasurementStartTime( Handle,ref s);
//*************
if (success)
{
success = MyBLF.BLSetWriteOptions( Handle, 6,0);
if (success)
{
BLF_Function.VBLObjectHeader vblobjectheaderclass = new BLF_Function.VBLObjectHeader();
BLF_Function.ObjectHeader objectheaderclass = new BLF_Function.ObjectHeader();
vblobjectheaderclass.mHeader.baseheader=objectheaderclass.baseheader;
BLF_Function.VBLAppTrigger apptriggerclass = new BLF_Function.VBLAppTrigger();
apptriggerclass.apptrigger.mFlags=(ushort)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
apptriggerclass.apptrigger.mHeader=vblobjectheaderclass.mHeader;
apptriggerclass.apptrigger.mHeader.baseheader.HeaderSize = apptriggerclass.apptrigger.mHeader.GetSize();
apptriggerclass.apptrigger.mHeader.baseheader.HeaderVersion = 1;
apptriggerclass.apptrigger.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
apptriggerclass.apptrigger.mHeader.baseheader.ObjectSize = (ushort)apptriggerclass.GetSize();
apptriggerclass.apptrigger.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_APP_TRIGGER;
apptriggerclass.apptrigger.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
BLF_Function.VBLCANMessage messageclass = new BLF_Function.VBLCANMessage();
messageclass.message.mHeader=vblobjectheaderclass.mHeader;
messageclass.message.mHeader.baseheader.HeaderSize = messageclass.message.mHeader.GetSize();
messageclass.message.mHeader.baseheader.HeaderVersion = 1;
messageclass.message.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
messageclass.message.mHeader.baseheader.ObjectSize = (ushort)messageclass.GetSize();
messageclass.message.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_CAN_MESSAGE;
messageclass.message.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
BLF_Function.VBLEnvVar variable_sclass = new BLF_Function.VBLEnvVar();
variable_sclass.variable_s.mHeader=vblobjectheaderclass.mHeader;
variable_sclass.variable_s.mHeader.baseheader.HeaderSize = variable_sclass.variable_s.mHeader.GetSize();
variable_sclass.variable_s.mHeader.baseheader.HeaderVersion = 1;
variable_sclass.variable_s.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
variable_sclass.variable_s.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ENV_STRING;
variable_sclass.variable_s.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
BLF_Function.VBLEnvVar variable_iclass = new BLF_Function.VBLEnvVar();
variable_iclass.variable_s.mHeader=vblobjectheaderclass.mHeader;
variable_iclass.variable_s.mHeader.baseheader.HeaderSize = variable_iclass.variable_s.mHeader.GetSize();
variable_iclass.variable_s.mHeader.baseheader.HeaderVersion = 1;
variable_iclass.variable_s.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
variable_iclass.variable_s.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ENV_INTEGER;
variable_iclass.variable_s.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
BLF_Function.VBLEthernetFrame ethframeclass = new BLF_Function.VBLEthernetFrame();
ethframeclass.ethframe.mHeader=vblobjectheaderclass.mHeader;
ethframeclass.ethframe.mHeader.baseheader.HeaderSize = ethframeclass.ethframe.mHeader.GetSize();
ethframeclass.ethframe.mHeader.baseheader.HeaderVersion = 1;
ethframeclass.ethframe.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
ethframeclass.ethframe.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_ETHERNET_FRAME;
ethframeclass.ethframe.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
BLF_Function.VBLAppText appTextclass = new BLF_Function.VBLAppText();
appTextclass.appText.mHeader=vblobjectheaderclass.mHeader;
appTextclass.appText.mHeader.baseheader.HeaderSize = appTextclass.appText.mHeader.GetSize();
appTextclass.appText.mHeader.baseheader.HeaderVersion = 1;
appTextclass.appText.mHeader.baseheader.signature = objectheaderclass.BL_OBJ_SIGNATURE;
appTextclass.appText.mHeader.baseheader.ObjectSize = (ushort)appTextclass.GetSize();
appTextclass.appText.mHeader.baseheader.ObjectType = (ushort)BLF_Function.ObjectHeader.OBJ_TYPR.BL_OBJ_TYPE_APP_TEXT;
appTextclass.appText.mHeader.mObjectFlags = (uint)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
for (int h=0;h<ethbuffer.Length;h++)
ethbuffer[h]=Convert.ToByte(h & 0xFF);
for (int i = 0; i < 1000 ; ++i)
{
/* increment in milliseconds */
time = (uint)(i * 100000);
/* setup app trigger object header */
apptriggerclass.apptrigger.mHeader.mObjectTimestamp = time;
/* write app trigger object */
success = Scrivi(Handle, apptriggerclass.apptrigger.mHeader.baseheader);////NO ERROR
written += success ? 1 : 0;
if (success)
{
string envdata1="01234567";
string envdata2="76543210";
/* setup CAN object header */
messageclass.message.mHeader.mObjectTimestamp = time;
/* setup CAN message */
messageclass.message.mChannel=1;
messageclass.message.mFlags=(byte)vblobjectheaderclass.BL_OBJ_FLAG_TIME_ONE_NANS;
messageclass.message.mDLC = 8;
messageclass.message.mID = 0x100;
char[] supp = envdata1.ToCharArray();
char[] supp2 = envdata2.ToCharArray();
messageclass.message.Data = new byte[messageclass.message.mDLC];
if ((i%2)==0)
{
for (int g=0;g<supp.Length;g++)
messageclass.message.Data[g] = (byte)supp[g];
}
else
{
for (int g=0;g<supp2.Length;g++)
messageclass.message.Data[g] = (byte)supp2[g];
}
/* write CAN message */
success = Scrivi(Handle, messageclass.message.mHeader.baseheader);////NO ERROR
written += success ? 1 : 0;
if (success)
{
if ((i%3)==0)
{
/* setup environment variable object headers */
variable_sclass.variable_s.mHeader.mObjectTimestamp= time;
/* setup environment variables */
string envname1="EnvString";
string envname2="EnvInt";
char[] suppstring1 = envname1.ToCharArray();
char[] suppstring2 = envname2.ToCharArray();
variable_sclass.variable_s.NameLength = (uint)envname1.Length;
variable_sclass.variable_s.DataLength = (uint)(((i%2)==0)?envdata1.Length:envdata2.Length);
variable_sclass.variable_s.Name = envname1;
variable_sclass.variable_s.Data = new byte[variable_sclass.variable_s.DataLength];
if ((i%2)==0)
{
for (int g=0;g<supp.Length;g++)
variable_sclass.variable_s.Data[g] = Convert.ToByte(supp[g]);
}
else
{
for (int g=0;g<supp2.Length;g++)
variable_sclass.variable_s.Data[g] = Convert.ToByte(supp2[g]);
}
variable_sclass.variable_s.mHeader.baseheader.ObjectSize = 65;
success = Scrivi(Handle, variable_sclass.variable_s.mHeader.baseheader);////ERROR
...........
}
public static bool Scrivi(int a, BLF_Function.ObjectHeader.ObjHeader b)
{
return MyBLF.BLWriteObject( a, ref b);
}
CB
答案 0 :(得分:1)
首先,类型HANDLE
应转换为IntPtr
,而不是int。
由于结构填充,结构的尺寸也可能与原始尺寸不同。使用C#代码中的[Structlayout()]
- 属性来控制它。
答案 1 :(得分:0)
将C#中的“ref”更改为“out”,并查看c ++代码中没有内存分配问题。