Форум » [x]Harbour » Передача массива в Си и обратно » Ответить

Передача массива в Си и обратно

Vladimir: Возникла задача передачи массива значений в C-функцию и его возврат в Harbour. В массиве целые и вещественные числа, символьные строки и логические значения. Экспертом С не являюсь, могу сделать что-то не слишком сложное и больше по образцу, но у меня получилось следующее. [more] Procedure Main Local aValues := { .T., 'string 1', .T., .F., 5689, 6.593, 'text', 126, 0.3,9 }, ; xItem, aNewVal Cls ? 'Before' ? '--------------------------' For each xItem in aValues ? HB_NtoS( xItem : __EnumIndex() ) + '=' + HB_ValToStr( xItem ) Next aNewVal := CTestArray( aValues ) ? 'After' ? '--------------------------' For each xItem in aNewVal ? HB_NtoS( xItem : __EnumIndex() ) + '=' + HB_ValToStr( xItem ) Next Return #pragma BEGINDUMP #include "hbapi.h" HB_FUNC_STATIC( CTESTARRAY ) { PHB_ITEM aValues = hb_param( 1, HB_IT_ARRAY ); HB_ULONG size = hb_arrayLen( aValues ); HB_ULONG i; void *data[ 20 ]; // Временные переменные // Для переноса в массив C int *tmpInt; long *tmpLong; float *tmpFloat; HB_BOOL *tmpBool; // Для возврата в Harbour int nInt; long nLong; float nFloat; HB_BOOL nBool; // Переносим значения for( i = 1; i <= size; ++i ) { switch ( hb_arrayGetType( aValues, i ) ) { case HB_IT_STRING: data[ i - 1 ] = hb_arrayGetC( aValues, i ); break; case HB_IT_INTEGER: tmpInt = ( int* ) malloc( sizeof( int ) ); *tmpInt = hb_arrayGetNI( aValues, i ); data[ i - 1 ] = tmpInt; free( ( int* ) *tmpInt ); // В BCC вызывает ошибку break; case HB_IT_LONG: tmpLong = ( long* ) malloc( sizeof( long ) ); *tmpLong = hb_arrayGetNL( aValues, i ); data[ i - 1 ] = tmpLong; free( ( long* ) *tmpLong ); // В BCC вызывает ошибку break; case HB_IT_DOUBLE: // В процедуре C используется тип float, а не double как // в Harbour, поэтому приводим тип tmpFloat = ( float* ) malloc( sizeof( float ) ); *tmpFloat = ( float ) hb_arrayGetND( aValues, i ); data[ i - 1 ] = tmpFloat; //free( ( float* ) *tmpFloat ); // Вызывает ошибку и в BCC, и в MinGW break; case HB_IT_LOGICAL: tmpBool = ( HB_BOOL* ) malloc( sizeof( HB_BOOL ) ); *tmpBool = hb_arrayGetL( aValues, i ); data[ i - 1 ] = tmpBool; free( ( HB_BOOL* ) *tmpBool ); // В BCC вызывает ошибку break; default: break; } } // Здесь делаем что-то со значениями data, не изменяя типы элементов. // .... // Формируем массив для передачи в Harbour hb_reta( size ); for( i = 1; i <= size; ++i ) { switch ( hb_arrayGetType( aValues, i ) ) { case HB_IT_STRING: hb_storvc( data[ i - 1 ], -1, i ); break; case HB_IT_INTEGER: nInt = (*(int *)data[ i - 1 ]); hb_storvni( (int) nInt, -1, i ); break; case HB_IT_LONG: nLong = (*(long *)data[ i - 1 ]); hb_storvnl( (long) nLong, -1, i ); break; case HB_IT_DOUBLE: nFloat = (*(float *)data[ i - 1 ]); hb_storvnd( (double) nFloat, -1, i ); break; case HB_IT_LOGICAL: nBool = (*(int *)data[ i - 1 ]); hb_storvl( (int) nBool, -1, i ); break; default: break; } } } #pragma ENDDUMP [/more] Код собирается без замечаний под MinGW и BCC55, но работает только собранный MinGW. Собранный BCC55 вызывает системную ошибку, но если закомментировать все вызовы free(), также работает. Может кто-нибудь ответить на следующее: как сделать поддержку и MinGW, и BCC55 в исходниках Harbour больше используются hb_xgrab() вместо malloc(), и hb_xfree() вместо free(). Может и здесь их применять, хотя по использованию и форме они вроде аналогичны. при возврате дробного числа теряются разряды (в Harbour получаем 6.59 вместо 6.593). Но если сделать установку Set decimals to 3, то всё нормально. Существует какой-нибудь способ избежать округления? Мне приходит в голову только возвращать в символьном виде с последующим переводом Val(), но может как-нибудь по другому?

Ответов - 0



полная версия страницы