Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.76/29: Рейтинг темы: голосов - 29, средняя оценка - 4.76
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24

Передача массива байт в .dll

31.12.2019, 21:53. Показов 7030. Ответов 75
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Никак не пойму каким образом правильно передать массив байт в библиотеку на С++ из программы на VB 6.0.
Код модуля:
Visual Basic
1
2
3
Public DPribor As String, CRCPribor As Integer, _
            num As Byte
Public Frame1() As Byte
Код программы:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Private Declare Function CRC_16 Lib "CRC_16.dll" _
        (ByRef Frame1() As Byte, num As Byte) As Integer
 
Private Sub Command1_Click()
DPribor = TxRx(2, 3, 0, 1, 0, 1)                         'Считать данные
End Sub
 
Function TxRx(ByRef Nport As Integer, ByRef Func As Integer, _
  ByRef Data1 As String, ByRef Data2 As String, ByRef Data3 As String, ByRef Data4 As String) As String
Frame1 = Nport & Func & Data1 & Data2 & Data3 & Data4
CRCPribor = CRC_16(Frame1, 5)
 Label3 = CRCPribor
End Function
Код библиотеки:
C++
1
2
3
4
5
6
7
8
9
10
11
#include "CRC_16.h"
#include <string>
using std::string;  // Чтобы постоянно не использовать std::string
unsigned short _stdcall CRC_16 (int *str[], int Length)
    {
unsigned short i, j, d;
        int Temp;
        i = 3;
                Temp = *str[i];
        return Temp;
}
Если в строке 8, i = 0, то выводится единица, Если i = другому числу (от 1 до 5), то библиотека зависает.
Судя по всему, я передаю адрес массива. Видимо, надо его преобразовать.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.12.2019, 21:53
Ответы с готовыми решениями:

Передача массива через write: Передается только 8 байт
Добрый день. Помогите пожалуйста, не понимаю, как передать заполненный двумерный динамический массив через функцию write. Что бы я не писал...

Загрузка неуправляемой Dll из массива байт
Привет всем! У меня есть библиотека Dll, написанная на C++. Я сделал над ней оболочку на C#, удобно реализующую функционал этой...

передача массива байт, протокл
Всем привет. Возник вопрос. Есть необходимость передать массив байт в комп от контроллера. Причем в зависимости от запроса передается...

75
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,038
Записей в блоге: 1
05.01.2020, 12:28
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Argus19 Посмотреть сообщение
unsigned int в VB - Integer.
В VB Integer - 2 байта. Нужен Long.
И int, вместо unsigned int.
0
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 14:00  [ТС]
Croessmah, сейчас всё заработало. Только CRC_16 не соответствует.
При передаче строки 2, 3, 7, 0, 0, 3 должен получить 048С, а получаю 09А0.
Ошибка была в том, что передавал Lengt числом. Сделал, как в примере DrOffset и "процесс пошёл". Обычная невнимательность. Неделя за компом может прилично отбить мозг.
0
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
05.01.2020, 14:54
Argus19, мб сначала разобраться с типами, способами передачей параметров в VB6?
В VB6 типы строк - BSTR. Все работа со строками в VB6 ведется в юникоде. При декларировании функции из DLL если нужно чтобы строки передавались как ANSI, то нужно параметр определять как ByVal As String (либо в библиотеке типов как LPSTR). В данном случае VB6 автоматом выполнить перевод строки из UNICODE в ANSI. Если необходимо передавать юникод то необходимо определять параметр как ByVal As Long и передавать как StrPtr(строка) (для библиотеки типов просто либо LPWSTR либо BSTR). Альтернативно можно задекларировать параметр как ByRef As Any и передавать как хочешь либо ByVal СТРОКА либо ByVal StrPtr(СТРОКА), также останется возможность передавать любые данные. Для ручного перевода строк из UNICODE в ANSI (и обратно) существует функция StrConv.

Добавлено через 9 минут
Цитата Сообщение от Argus19 Посмотреть сообщение
unsigned int в VB - Integer.
Нет, откуда такое вообще взялось?
Мало того что unsigned тип в vb6 только один - это BYTE, так int - это вообще-то Long.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 16:37
The trick, автору ведь не нужна работа со строками. Ему нужно посчитать контрольную сумму от последовательности байт. С этой точки зрения все равно, строка там или что еще, главное, чтобы был правильный указатель на начало последовательности и ее размер.

Однако учитывая, что строка в VB действительно юникодная (а точнее - UTF16), то байт приходит в функцию на С++ в два раза больше, чем автор написал символов.

Argus19, т.е. на стороне С++, когда вы передаете строку "237003", на самом деле получается такая последовательность
C++
1
    unsigned char p[] = {'2', 0, '3', 0, '7', 0, '0', 0, '0', 0, '3', 0};
Это следует учитывать, когда вы проверяете свою контрольную сумму. Потому что вероятнее всего вы считаете ее для такой последовательности:
C++
1
    unsigned char p[] = {'2', '3', '7', '0', '0', '3'};
и закономерно не получаете совпадения.

Если нужен именно второй вариант, то на стороне VB можно сделать так:
Visual Basic
1
Frame1 = StrConv(Nport & Func & Data1 & Data2 & Data3 & Data4, vbFromUnicode)
1
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 16:50  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Нет, откуда такое вообще взялось?
неправильно написал. В .dll unsigned int? в VB Integer.
Цитата Сообщение от DrOffset Посмотреть сообщение
на стороне С++, когда вы передаете строку "237003", на самом деле получается такая последовательность
Для проверки попробовал вставлять числа от 0 до 3 в конструкцию:
C++
1
2
Temp = (str[2]- 48);
        return Temp;
получил последовательность: 2, 208, 3, 208
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 16:52
Цитата Сообщение от Argus19 Посмотреть сообщение
Для проверки попробовал вставлять числа от 0 до 3 в конструкцию:
Для проверки чего?
0
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 17:00  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Для проверки чего?
того, что вводится в библиотеку.
Получается, что не, как вы писали: 2,0,3,0, а 2,208,3,208. Откуда число 208 непонятно.
Lenght, как вы писали равно 12.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 17:18
Цитата Сообщение от Argus19 Посмотреть сообщение
Получается, что не, как вы писали: 2,0,3,0, а 2,208,3,208. Откуда число 208 непонятно.
Нет, все именно так, как я написал.

Добавлено через 4 минуты
Цитата Сообщение от Argus19 Посмотреть сообщение
Откуда число 208 непонятно.
Второй байт - 0, так, как я написал, от него вы отнимаете 48, получаете -48.
-48 - это 208 в беззнаковом представлении.
Иными словами, все именно так, я как я описывал, а вы сами сделали число 208 путем нехитрых манипуляций.

Добавлено через 7 минут
Argus19, т.е. тут скорее вопрос к вам, нафига вы отнимаете 48 от значений байтов, которые вам пришли в функцию?

Добавлено через 1 минуту
Вот наглядная демонстрация работы: https://rextester.com/QWETNX89062
Обе ваши заявленные контрольные суммы
Цитата Сообщение от Argus19 Посмотреть сообщение
При передаче строки 2, 3, 7, 0, 0, 3 должен получить 048С, а получаю 09А0.
присутствуют в выводе.
1
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
05.01.2020, 17:35
Цитата Сообщение от DrOffset Посмотреть сообщение
The trick, автору ведь не нужна работа со строками. Ему нужно посчитать контрольную сумму от последовательности байт. С этой точки зрения все равно, строка там или что еще, главное, чтобы был правильный указатель на начало последовательности и ее размер.
Ему именно и нужна работа со строками, а именно тип строк и способы передачи. Нужно знать как работать и передавать строки в VB6 чтобы получить тот или иной результат, о чем я и написал.

Добавлено через 44 секунды
Цитата Сообщение от DrOffset Посмотреть сообщение
Если нужен именно второй вариант, то на стороне VB можно сделать так:
Можно просто передать ByVal Строка
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 17:49
The trick, традиционно функция расчета CRC не принимает строку, она принимает указатель на последовательность байт. Что за последовательностью стоит - строка или что-то еще, дело десятое.

Добавлено через 9 минут
Цитата Сообщение от The trick Посмотреть сообщение
Нужно знать как работать и передавать строки в VB6 чтобы получить тот или иной результат, о чем я и написал.
Дык я с этим и не спорил.
Просто я хотел обратить внимание, что в изначальной постановке о непосредственно строках не шла речь.
Автор с самого начала передавал туда массив байт.
И если ему, предположим, нужно посчитать CRC от юникодной строки, то того кода было бы достаточно. Мы просто рассматриваем строку как массив байт и считаем. Алгоритму CRC все равно, два там байта на символ или один, или четыре. Поэтому я и сказал, что автору не нужна работа со строками, но конечно же ему нужно понимать как правильно передать такую строку, чтобы можно было поработать с последовательностью байт из которых она состоит.
1
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
05.01.2020, 19:07
Цитата Сообщение от DrOffset Посмотреть сообщение
The trick, традиционно функция расчета CRC не принимает строку, она принимает указатель на последовательность байт. Что за последовательностью стоит - строка или что-то еще, дело десятое.
Кто-то с этим спорил? Я хорошо осведомлен как работает CRC.

Цитата Сообщение от DrOffset Посмотреть сообщение
Автор с самого начала передавал туда массив байт.
Если обратить внимание на то как он формирует массив, то становится очевидно что он работает со строкой. В частности эта строка:
Visual Basic
1
Frame1 = Nport & Func & Data1 & Data2 & Data3 & Data4
- это конкатенация BSTR строк. Строк в юникоде. Далее просто формируется массив который имеет тоже самое содержимое как и юникодная BSTR строка. Ему, очевидно, нужно найти контрольную сумму этой строки, но ANSI. Ему вообще не нужно для этого создавать какой-то дополнительный массив и т.п., а можно просто передать строку как ByVal. О чем я и написал.
1
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 19:32  [ТС]
DrOffset, The trick, большое спасибо за помощь. Сравнил со скриншотом работы ОРС сервера. Всё получилось.
Виноват я. Хотел соблюсти передачу данных так же, как в VB, чтобы сравнить результат.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 19:50
Цитата Сообщение от The trick Посмотреть сообщение
это конкатенация BSTR строк. Строк в юникоде.
Прекрасно это знаю.

Цитата Сообщение от The trick Посмотреть сообщение
но ANSI.
Как раз таки именно процитированное и не очевидно.
Почему бы ему не хотеть посчитать контрольную сумму от юникода?
Явно об этом нигде не говорилось.

Добавлено через 4 минуты
Цитата Сообщение от The trick Посмотреть сообщение
Кто-то с этим спорил? Я хорошо осведомлен как работает CRC.
Да никто не спорил, я просто пояснил к чему я вообще написал то, что выше. Это по идее должно было снять ваши вопросы, я не критиковал ваш пост, я просто уточнил для ТС, что возможно ему не нужно глубоко погружаться в работу со строками.
0
Модератор
10061 / 3906 / 885
Регистрация: 22.02.2013
Сообщений: 5,856
Записей в блоге: 79
05.01.2020, 20:07
Цитата Сообщение от DrOffset Посмотреть сообщение
Прекрасно это знаю.
А для чего тогда ненужное преобразование в массив? Можно же сразу передать строку, и нужные преобразования (если нужно) VB6 сделает за нас.

Цитата Сообщение от DrOffset Посмотреть сообщение
Как раз таки именно процитированное и не очевидно.
Очевидно, если посмотреть на его сообщения.

Цитата Сообщение от DrOffset Посмотреть сообщение
Почему бы ему не хотеть посчитать контрольную сумму от юникода?
Потому что он использовал std::string а не std::wstring. Ну и далее по теме видно что он получает юникод, хотя ожидает ANSI.

Цитата Сообщение от DrOffset Посмотреть сообщение
Да никто не спорил, я просто пояснил к чему я вообще написал то, что выше. Это по идее должно было снять ваши вопросы, я не критиковал ваш пост, я просто уточнил для ТС, что возможно ему не нужно глубоко погружаться в работу со строками.
Цитата Сообщение от DrOffset Посмотреть сообщение
The trick, автору ведь не нужна работа со строками.
Меня смутил этот пост. Честно, я так и не понял что Вы имели в виду, т.к. как раз работа со строками, понимание типа строк, внутренней "кухни" работы со строками в VB6 тут и нужны. Там есть не очевидные вещи на которых можно "споткнуться".
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 20:23
Цитата Сообщение от The trick Посмотреть сообщение
А для чего тогда ненужное преобразование в массив?
Оно было у ТС. Он не показывал весь код, поэтому лично мне не очевидно, что он был не нужен.

Цитата Сообщение от The trick Посмотреть сообщение
Очевидно, если посмотреть на его сообщения.
Он только написал, что результат не совпадает с его ожиданием. Но это не значит, что он в действительности ожидал именно этого. Может быть он просто неправильно получил ожидаемый результат?

Цитата Сообщение от The trick Посмотреть сообщение
Потому что он использовал std::string а не std::wstring. Ну и далее по теме видно что он получает юникод, хотя ожидает ANSI.
std::string он использовал неправильно. К тому же в С++ вполне допускается хранить в std::string произвольные данные. Этим активно пользуется, например, google::protobuf. (Это не значит, что я поддерживаю эту практику, но значит, что зная это, я не могу допускать однозначных трактовок, как вы сейчас).

Цитата Сообщение от The trick Посмотреть сообщение
Честно, я так и не понял что Вы имели в виду, т.к. как раз работа со строками, понимание типа строк, внутренней "кухни" работы со строками в VB6 тут и нужны.
Я просто предположил, что интерпретация его данных как строки и дополнительные преобразования кодировок могут оказаться не нужны в его задаче. Строка у него получилась там - да, и проблемы с юникодом в нагрузку, но я предположил, что это побочный эффект того, что он хотел сделать. Да и если касаться стороны С++, то на стороне С++ нет строк в этой задаче.
А с тем, что нужно понимать как передавать данные из VB - я и не спорил. Я же сам ему объяснял про это выше и про связь с юникодом.
0
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 20:34  [ТС]
The trick, DrOffset, из .dll можно получить только одно значение, что осложняет её разработку.
В посте №48 ссылка на код консольного приложения.
Возможно ли передавать строки или массивы из VB 6.0 в консольное приложение на С++? Если да, то разработка .dll может упроститься, т.к. можно выводить промежуточные результаты.
Не только я, а, скорее всего, просто начинающие не знают о взаимодействии VB и С++. Прекрасная тема для статьи.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 20:36
The trick, Короче, наш разговор на самом деле не очень полезен для темы.
Я просто скажу, что к тому, что вы говорили здесь по сути, у меня нет никаких претензий. Мое цитирование вас было сделано лишь для того, чтобы было понятно в каком контексте я собираюсь продолжать тему и связано это с допущением возможности, что получившийся массив байт из юникодной строки - это именно то, что нужно было ТС, а он сам просто еще не понял так это или нет. Дополнительно к этому, я хотел предостеречь ТС от восприятия этой задачи, как задачи работы со строками (к этому меня подвигло неожиданное использование им std::string в контексте, где оно не только не нужно, но и вредно), тогда как работа со строками здесь является только побочным эффектом и заканчивается на стороне VB.
1
 Аватар для Argus19
1450 / 467 / 78
Регистрация: 24.09.2017
Сообщений: 2,557
Записей в блоге: 24
05.01.2020, 20:47  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Дополнительно к этому, я хотел предостеречь ТС от восприятия этой задачи, как задачи работы со строками (к этому меня подвигло неожиданное использование им std::string в контексте, где оно не только не нужно, но и вредно), тогда как работа со строками здесь является только побочным эффектом и заканчивается на стороне VB.
Modbus RTU - двоичный протокол с передачей байт в обоих направлениях.
Не на всяком предприятии нужна SCADA, часто достаточно автоматизировать только сбор данных. Покупать SCADA чтобы использовать только часть её функций "жаба задушит". Проще написать свою программу. На VB 6.0 всё нормально пишется и работает. Я написал с использованием MSComm, затем перешёл на использование Win32API, что решило проблему переносимости.
.dll на С++ прекрасно используются в VB и других ЯП. Задумка в написании библиотеки на С++ для реализации протокола Modbus RTU, чтобы можно было её использовать из других ЯП.
0
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
05.01.2020, 20:51
Цитата Сообщение от Argus19 Посмотреть сообщение
Возможно ли передавать строки или массивы из VB 6.0 в консольное приложение на С++?
Возможно. Но лично мне никаких простых решений в голову не приходит.
Сложность организации этого взаимодействия превосходит сложность вашей задачи в целом.

Цитата Сообщение от Argus19 Посмотреть сообщение
Если да, то разработка .dll может упроститься, т.к. можно выводить промежуточные результаты.
Вы можете открыть консоль из DLL и выводить результаты туда.
Кусочек кода DLL:
C++
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
#include <windows.h>
#include <cstdio>
 
class Console
{
public:
    Console() {
        AllocConsole();
        freopen("CONOUT$", "w", stdout);
    }
    ~Console() {
        FreeConsole();
    }
};
 
static void init_console()
{
    static Console con;
}
 
unsigned short __stdcall DLL_EXPORT CRC_16(unsigned char * c, unsigned int length)
{
    init_console();
 
    unsigned short crc = 0xFFFF;
    while(length--)
    {
        unsigned char x = crc >> 8 ^ *c++;
        x ^= x >> 4;
        crc = (crc << 8) ^ ((unsigned short)(x << 12)) ^ ((unsigned short)(x << 5)) ^ ((unsigned short)x);
 
        std::printf("%d ", (int)x);
    }
    return crc;
}
1
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,038
Записей в блоге: 1
05.01.2020, 20:53
Цитата Сообщение от Argus19 Посмотреть сообщение
Задумка в написании библиотеки на С++ для реализации протокола Modbus RTU
Libmodbus. Библиотека Modbus for Linux, Mac OS X, FreeBSD, QNX and Win32
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.01.2020, 20:53

Передача массива байт как поля объекта
Добрый день. Есть класс-оболочка БД &quot;Data&quot;. public class Data { public string Command { get; set; } ...

Передача массива в dll
Не могли бы обьяснить как реализовать сабж?(возможно ссылку на теорию) Пробовал и в тупую передавать массив и через указатель, во всех...

Передача массива в dll-функцию
Доброго дня. Нужна помощь в решении следующей проблемы. Есть DLL (написана на Delphi), в которой имеем: type TIntArray = Array...

Передача массива из DLL в основную программу
В DLL у меня происходят вычисления и в основную программу передается массив записей. Но, почему то после успешной отработки DLL я не могу...

Передача двумерного динамического массива в функцию, определенную в DLL
Всем дня хорошего. Подскажите пожалуйста, как в функцию, определенную в DLL, передать двумерный динамический массив в качестве параметра....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Установка нескольких штампов электронной подписи в строго определенных местах файла docx
ВладимирСамохин 19.07.2026
(В!) Работа с Электронной подписью - это неотъемлемая часть современного документооборота. Но что делать, если нужно поставить несколько штампов электронной подписи в строго определенных местах. . .
сукцессия 35. Научная статья о проделанной работе
anaschu 19.07.2026
Написал в формате латекс и пдф
Вангую, что это не пройдёт модерацию, и на неделе я запущу свой сервер.
Hrethgir 19.07.2026
Эта публикация сейчас в песочнице и ждёт приглашения. https:/ / habr. com/ ru/ sandbox/ 295048/ начало и оглавление - Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование. . .
сукцессия 33. открытые вопросы от клауде
anaschu 19.07.2026
"Что накопилось за эту часть А — тринадцать правок, из которых шесть пришли из ваших вопросов и каждая оказалась реальной ошибкой, а не калибровкой: односторонний симбиоз, отсутствующий листопад,. . .
32 сукцессия
anaschu 19.07.2026
сукцессия 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не «подкручивает» сходимость —. . .
сукцессия 31: модель микоризы - это модель ещё нескольких явлений, социальных и экономических
anaschu 18.07.2026
Теория «Всего»: апдейт v1. 1. 2 — 28‑мерное ядро стабилизировано Коллеги, фиксирую разбор инженерных правок и их изоморфную проекцию на экономику, меметику и половой отбор. Модель теперь не. . .
сукцессия 30. Массив проверяющих друг друга моделей
anaschu 18.07.2026
Архитектура сети взаимопроверяющих моделей микоризной сукцессии (v2. 0) Развитие тензорного ОДУ-ядра и создание кросс-платформенного калибровочного полигона Уважаемые коллеги! В продолжение. . .
Грибы - это женщины, деревья - это мужчины. Анти инь янь для союза мужчины и женщины.
anaschu 18.07.2026
ГЛАВНЫЙ НАУЧНО-ФИЛОСОФСКИЙ ВЫВОД: Сексуально-Репродуктивный Капитализм против Государства Моногамии Коллеги, мы вышли на финишную прямую 20-мерного ОДУ-моделирования вековой сукцессии (ветка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru