Passing char*and struct in C# to c++ DLL, all variables pass successfully except one
I have written a c++ wrapper dll for a C dll with lib file I have, now everything is partially working, all the functions I have written in the c++ wrapper class work as expected bar one.
Here 开发者_运维百科it is in the C++ dll
__declspec(dllexport) long ReadRawDataByTime(char * tagname, long serverhandle, IHU_TIMESTAMP * StartTime, IHU_TIMESTAMP * EndTime, int * number_of_samples, IHU_DATA_SAMPLE **data_values){
return ihuReadRawDataByTime(serverhandle, tagname, StartTime, EndTime, number_of_samples, data_values);
}
and here is my definition and how I call it in C#
[DllImport("IHUAPIWrapper.dll")]
public static extern long ReadRawDataByTime(String tagname, long serverhandle, IHU_TIMESTAMP* StartTime, IHU_TIMESTAMP* EndTime, int* number_of_samples, IHU_DATA_SAMPLE** data_values);
...
long lRet = ReadRawDataByTime
(
tagname,//the handle returned from the connect
serverhandle, //the single tagname to retrieve
&temp_start_time, //start time for query
&temp_end_time, //end time for query
&number_of_samples, //will be set by API
&pSamples //will be allocated and populated in the user API
);
where tagname is defined as a string and the rest are their appropriate structs.
Now if I set the debugger in the C++ dll I can see all the values being passed in correctly, serverhandle is as expected, tagname holds the correct string, endTime has the correct time, number of samples and pSamples are blank as expected however startTime is 'undefined' when I am definitely passing in a valid struct.
If I dummy up the variables in the debugger it even returns expected data it just appears it is not passing the variables correctly.
I did some experimentation and swapped the order of the variables so serverhandle was passed first and tagname was passed second, if I do this all the variables are correct except tagname is now 'undefined'
is there something wrong with how I am passing the string that is corrupting the next variable? do I need to specifiy some special calling convention and currently it is just a fluke that everything else works?
Any help would be much appreciated. :)
edit: here is a screenshot of the debugger to show what I mean about all variables being passed except one.
Lots of red flags here. It doesn't work because you didn't specify CallingConvention.Cdecl. And the long arguments are int on the C# side. That will take care of your original problem, everything should be passed correctly now. Start another question when the pointers cause an AccessViolation.
Are you compiling your DLL as unicode?
Anyway I think you need to convert your string to a byte array before passing it
Found the problem, issue is in C++ in visual studio longs are 4 bytes long, in C# they are 8 bytes long, also chars are unicode and 2 bytes long, and 1 byte in C++ this meant my struct sizes were different between the two which is why the parameters didn't pass correctly, also why I got an access violation as the pointers incremented too far.
Cheers for all the help everyone, all works perfectly now
here is how I finally did it as well if anyone is interested
[DllImport("IHUAPIWrapper.dll",CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadRawDataByTime(string tagname, int serverhandle, ref IHU_TIMESTAMP StartTime, ref IHU_TIMESTAMP EndTime, out IntPtr number_of_samples, out IntPtr data_values);
IntPtr thisPtr = new IntPtr(pSamples_ptr.ToInt32() + (sizeof(IHU_DATA_SAMPLE) * loop));
IHU_DATA_SAMPLE data_sample = (IHU_DATA_SAMPLE)Marshal.PtrToStructure(thisPtr, typeof(IHU_DATA_SAMPLE));
精彩评论