Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type) / 8 сообщений из 8, страница 1 из 1
26.08.2009, 20:28
    #36164876
nrmBeginner
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
Уважаемые знатоки, возникла не понятная для меня проблема с передачей данных из программы пишущейся на VB6 в библиотечную функцию пишущуюся на C++ и компилированную MinGW (codeblocks).

передача осуществляется посредством передачи адреса на структуру:

С++:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
struct ostrovodrinstruct {
    char * entitycardnum;
    char * entityfio;
    char * street;
    char * house;
    char * flat;
    double area;
    char * order;
};

int WINAPI DLL_EXPORT ostrovodrep(ostrovodrinstruct * oodrin, char * szoutput);


VB6:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Public Type ostrovodrinstruct
    entitycardnum As String
    entityfio As String
    street As String
    house As String
    flat As String
    area As Double
    order As String
End Type

Declare Function ostrovodrep Lib "...\ostrovodrep.dll" _
    Alias "ostrovodrep@8" (oodrin As ostrovodrinstruct, ByVal szoutput As String) As Long

Все работает отлично пока не начинается обращение к ostrovodrinstruct::order, переданной в библиотечную функцию, внутри самой библиотеки - когда библ.функция доходит до обращения к переменной то VB программа выдает ошибку:

Инструкция по адресу "0x..." обратилась к памяти по адресу "0x...". Память не может быть "read"

"OK" -- завершение приложения
"Отмена" -- отладка приложения

После нажатия "OK" среда VB6 в которой приоизводился запуск вылетает.
Пробовал в структуру добавлять еще одно поле в конце без его использования - ошибку не выдает за то order пустое. Пробовал вызывать библиотеку из программы написанной на C++ - все работает отлично, но библиотека должна использоваться именно для программы на VB6.
...
Рейтинг: 0 / 0
26.08.2009, 23:28
    #36165005
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
nrmBeginner,
проявляется ли ошибка, если поле double area сделать в структуре первым, а не шестым?
...
Рейтинг: 0 / 0
29.08.2009, 21:18
    #36169277
nrmBeginner
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
Весьма странно, но сработало. А почему так, что это баг, правило языка?

char * order сработала, а вот теперь появилась другая не менее смешная проблема: данные из этой структуры попутались в памяти с данными другой структуры:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
Type inhabitantsstruct
    datain As odrdate
    fio As String
    birthyear As Integer
    relationship As String
End Type

Type ostrovodrinstruct
    area As Double
    entitycardnum As String
    entityfio As String
    street As String
    house As String
    flat As String
    order As String
End Type

Public odrin As ostrovodrinstruct
Public inhs( 2 ) As inhabitantsstruct

Структуры передаются разными библиотечными функциями. В inhs(1 и 2).fio почемуто данные из строки принадлежащей odrin.order, а в inhs(1 и 2).relationship данные из odrin.street.
Я проверял, до передачи структур в библиотечные функции все данные правильны, а после передачи, данные внутри функции испорчены, а в вызывающей программе по завершении библиотечной процедуры, в своих структурах данные правильные.
...
Рейтинг: 0 / 0
30.08.2009, 02:05
    #36169393
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
nrmBeginnerВесьма странно, но сработало. А почему так, что это баг, правило языка?Нет, не странно. Надо соблюдать соглашения по передаче параметров. Для параметров-структур существуют такие понятия как выравнивание членов структуры и выравнивание самой структуры. За первое в MSVC (про MinGW не знаю) отвечают прагма pack() и/или ключ компилятора /Zp n , за второе - описатель __declspec(align(#)). Подробности здесь . Для передачи/приёма структур в/из процедуры VB надо для членов структур использовать выравнивание 4 (вероятно, в MinGW по умолчанию стоит 8), выравнивание структуры явно не указывать (в этом случае будет выравниваться автоматически по максимальному выравниванию своих членов). Итого:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
#pragma pack(push,  4 )
struct ostrovodrinstruct {
    char * entitycardnum;
    char * entityfio;
    char * street;
    char * house;
    char * flat;
    double area;
    char * order;
};
#pragma pack(pop)
nrmBeginnerтеперь появилась другая не менее смешная проблема: данные из этой структуры попутались в памяти с данными другой структуры:
...
Структуры передаются разными библиотечными функциями. В inhs(1 и 2).fio почемуто данные из строки принадлежащей odrin.order, а в inhs(1 и 2).relationship данные из odrin.street.
Я проверял, до передачи структур в библиотечные функции все данные правильны, а после передачи, данные внутри функции испорчены, а в вызывающей программе по завершении библиотечной процедуры, в своих структурах данные правильные.Возможно, неправильно передаёте массив. Приведите описания данных и функций на обоих сторонах и код вызова хотя бы.
...
Рейтинг: 0 / 0
02.09.2009, 20:52
    #36175656
nrmBeginner
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
БенедиктНадо соблюдать соглашения по передаче параметров
Где про это можно почитать не подскажете? Только по русски по возможности,а то я по английски со словарем читаю. И если располагаете информацией о том где можно прочитать грамотную информацию о том что есть выравнивание и с чем его едят. Читал что для повышения быстродействия выравнивют данные к четным адресам когда пишут на ассемблере, но вижу этого не достаточно знать.


БенедиктПриведите описания данных и функций на обоих сторонах и код вызова хотя бы.

c++:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
struct odrdate {
    //What number, which evaluated as first, is with indifference
    short wyear;
    short wmonth;
    short wday;
};

struct inhabitantsstruct {
    odrdate datain;
    char * fio;
    short birthyear;
    char * relationship;
};

struct ostrovodrinstruct {
    double area;
    char * entitycardnum;
    char * entityfio;
    char * street;
    char * house;
    char * flat;
    char * order;
};

extern "C"
{
int WINAPI DLL_EXPORT ostrovodrep(const ostrovodrinstruct * oodrin, char * szoutput);
void WINAPI DLL_EXPORT addinhabitant(inhabitantsstruct* inhabitant);
}

vb:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
.bas:

Type odrdate
    'What number, which evaluated as first, is with indifference
    wyear As Integer
    wmonth As Integer
    wday As Integer
End Type


Type inhabitantsstruct
    datain As odrdate
    birthyear As Integer
    fio As String
    relationship As String
End Type


Type ostrovodrinstruct
    area As Double
    entitycardnum As String
    entityfio As String
    street As String
    house As String
    flat As String
    order As String
End Type

Public odrin As ostrovodrinstruct
Public inhs( 2 ) As inhabitantsstruct

Declare Function ostrovodrep Lib "E:\CBproj\ostrovodrep\bin\Debug\ostrovodrep.dll" _
    Alias "ostrovodrep@8" (oodrin As ostrovodrinstruct, ByVal szoutput As String) As Long

Declare Sub addinhabitant Lib "E:\CBproj\ostrovodrep\bin\Debug\ostrovodrep.dll" _
    Alias "addinhabitant@4" (ByRef inhabitant As inhabitantsstruct)


.frm:

Private Sub Command1_Click()
    inhs( 1 ).fio = "Василий Васильевич Пупкин"
    inhs( 1 ).datain.wyear =  1996 
    inhs( 1 ).datain.wmonth =  6 
    inhs( 1 ).datain.wday =  5 
    inhs( 1 ).birthyear =  1987 
    inhs( 1 ).relationship = "брат"

    inhs( 2 ).fio = "Петр Васильевич Пупкин"
    inhs( 2 ).datain.wyear =  2003 
    inhs( 2 ).datain.wmonth =  6 
    inhs( 2 ).datain.wday =  5 

    inhs( 2 ).birthyear =  1979 
    inhs( 2 ).relationship = "Кто это???"

    odrin.entitycardnum = "000535903891"
    odrin.entityfio = "Василий Васильевич Пупкин"
    odrin.street = "Ленина"
    odrin.house = "17"
    odrin.flat = "13"
    odrin.area =  50 . 5 
    odrin.order = "Пасспорт Российской Федерации"

    addinhabitant inhs( 1 )
    addinhabitant inhs( 2 )
    
    ostrovodrep odrin, App.Path & "\report.ods"
End Sub
...
Рейтинг: 0 / 0
03.09.2009, 12:03
    #36176425
nrmBeginner
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
Наверно этого не достаточно, вот еще:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
inhabitantsstruct *inhabitants;
short inhsmax= 0 ;
short inhscur= 0 ;

extern "C" void WINAPI DLL_EXPORT addinhabitant(inhabitantsstruct* inhabitant)
{
    inhabitantsstruct *inhstmp;
    if(inhscur==inhsmax) {
        inhsmax+= 10 ;
        inhstmp = new inhabitantsstruct[inhsmax];
        for(int i= 0 ;i<inhscur;i++) {
            inhstmp[i] = inhabitants[i];
        }
        delete inhabitants;
        inhabitants = inhstmp;
    }

    inhabitants[inhscur] = *inhabitant;
    inhscur++;
}
...
Рейтинг: 0 / 0
07.09.2009, 18:10
    #36182632
Бенедикт
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
nrmBeginnerГде про это можно почитать не подскажете?В документации по используемому компилятору.nrmBeginnerТолько по русски по возможности,а то я по английски со словарем читаю.Не знаю, где можно почитать по-русски. Возможно, в книгах по C++. Поиском находятся темы в форумах, но это неофициальная информация, подходить к ней надо критически. Могу посочувствовать - сам начинал со чтения со словарём. Потом без словаря. Потом стал английскую документацию стал читать быстрее чем русскую, т. к. она компактнее, не содержит ошибок перевода и сомнительных терминов.nrmBeginnerИ если располагаете информацией о том где можно прочитать грамотную информацию о том что есть выравнивание и с чем его едят.Я дал ссылку. Попробуйте для начала не обращать внимание на __declspec(align(#)) и понять 4 правила, описанные после слов "To summarize".

По коду.
1) Непонятно, было ли применено выравнивание структур в коде на C++.
2) Описание структуры inhabitantsstruct в VB не соответствует описанию в C++.
3) Да, "этого не достаточно" было. С кодом addinhabitant() стало понятно, в чём дело.
Первая ошибка идеологическая. Если Вы создаёте некий контейнер (в данном случае inhabitants[]), то храните в нём либо копии объектов, либо ссылки на объекты которые не могут быть уничтожены без ведома контейнера. У вас ни то, ни другое, и имеет место
Вторая ошибка - техническая. Строки переменной длины VB в мире C/C++ называются BSTR. При передаче их во внешние функции VB преобразует BSTR во временный ABSTR. В принципе, можно интерпретировать BSTR и ABSTR как wchar_t* и char* соответственно, хотя реальная картина сложнее. Но после вызова внешней функции временный ABSTR уничтожается. Т. е. сохранённые в контейнере char* указывают уже в никуда, по большому счёту.
...
Рейтинг: 0 / 0
08.09.2009, 00:08
    #36182968
Андрей159
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type)
Возможно это связано с явным обтявлением в TYPE ?
TYPE
....
relationship As String*100
...
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Ошибка в передаче конкретной строки в библиотеку на C++ через структуру (Type) / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]