Передача char * и struct в C # в c ++ DLL, все переменные успешно проходят, кроме одной - PullRequest
0 голосов
/ 17 февраля 2011

Я написал dll-оболочку c ++ для dll-библиотеки C с имеющимся у меня файлом lib, теперь все частично работает, все функции, которые я написал в классе-оболочке c ++, работают, как и ожидалось, одна строка.

Здесьэто в 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);
}

, и вот мое определение и как я называю его в 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
                );

, где tagname определен как строка, а остальные являются их соответствующими структурами.

Теперь, если я установлю отладчик в dll C ++, я вижу, что все значения передаются правильно, дескриптор сервера соответствует ожидаемому, tagname содержит правильную строку, endTime имеет правильное время, количество выборок и pSamplesявляются пустыми, как и ожидалось, однако startTime является неопределенным, когда я определенно передаю допустимую структуру.

Если я перебираю переменные в отладчике, он даже возвращает ожидаемые данные, просто кажется, что он не передает переменные правильно.

Я немного поэкспериментировал и поменял местами порядок переменных, чтобы сначала передавался дескриптор сервера и тэгпрошло второе, если я делаю это, все переменные верны, за исключением того, что tagname теперь 'undefined'

что-то не так с тем, как я передаю строку, которая портит следующую переменную?мне нужно указать какое-то специальное соглашение о вызовах, и в настоящее время это просто случайность, что все остальное работает?

Любая помощь будет высоко ценится.:)

edit: вот скриншот отладчика, чтобы показать, что я имею в виду для всех передаваемых переменных, кроме одной.http://img602.imageshack.us/img602/5281/47739520.jpg

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

Много красных флагов здесь. Это не работает, потому что вы не указали CallingConvention.Cdecl. И аргументы long int на стороне C #. Это позаботится о вашей первоначальной проблеме, теперь все должно пройти правильно. Начните другой вопрос, когда указатели вызывают AccessViolation.

0 голосов
/ 22 февраля 2011

Обнаружена проблема, проблема в C ++: в Visual Studio длинные - 4 байта, в C # - 8 байтов, также символы в юникоде и 2 байта, а в C ++ 1 байт. два, именно поэтому параметры не прошли правильно, а также потому, что я получил нарушение доступа, так как указатели слишком сильно увеличились.

Всем привет за помощь, теперь все работает отлично

вот как я наконец сделал это, если кому-то интересно

[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));
0 голосов
/ 17 февраля 2011

Вы компилируете свою DLL как Unicode?

В любом случае, я думаю, вам нужно преобразовать вашу строку в байтовый массив, прежде чем передавать ее

...