Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1

С++-библиотека-фреймворк для VBxx

07.10.2025, 02:21. Показов 2928. Ответов 41
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всязи с недавно открывшейся возможностью по написанию такой библиотеки, появилась мысль по написанию такой библиотеки, хотя такая мысль была у меня давно, но не было возмжоности, а теперь есть возможность, надо бы найти мысль, надо ее вспомнить, то о чем я думал. Если перейти к конкретике, я думал, о том, чего не хватает в VB и то что это на самом деле не так сложно восполнить, зная С/С++ (или другие компилируемые языки, тот же пурик, дельфин и пр.). Чуть позже составлю примерный список из того, что можно было реализовать исходя из моего слегка ограниченного видения..

Добавлено через 11 минут
1) InStr для массивов. Итак, начнем с функции InStr. Не хватает реализации этой функции для массивов, говоря по иному, чтобы функция могла искать блок памияти в другом блоке памяти, реализовать хочу, как поиск любого массива внутри любого массива (не ссылочного ест-но)
2) RichEdit также как здесь. Это сложновато, но надеюсь на нейросеть и ее натасканность нейросетей на C++ и готовую кодовую базу по этому оконному элементу.
3) различные строковые функции из js/php/python.
4) MemCopy, GetMem*, PutMem* для VBA
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.10.2025, 02:21
Ответы с готовыми решениями:

Можно ли программно подключить библиотеку VBA, в частности библиотеку Microsoft Visual Basic for Application Extensebility?
Кто знает, можно ли программно подключить библиотеку VBA, в частности библиотеку Microsoft Visual...

Нужна библиотека с функциями для работы с файлами
Я разрабатываю операционную оболочку на QBasic'e - QuickGUI (quickgui.narod.ru), и сейчас нужно...

Помогите пожалуйста с Инициализацией Dll библиотеки
После компиляции проекта требуется обновить dll библиотеку без повторной компиляции проекта. Можно...

41
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
02.11.2025, 09:21
Цитата Сообщение от testuser2 Посмотреть сообщение
4) MemCopy, GetMem*, PutMem* для VBA
VBA пользуюсь очень редко. Эти функции в нём не вызываются из Win 32 API?
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
02.11.2025, 15:16  [ТС]
Цитата Сообщение от Argus19 Посмотреть сообщение
Эти функции в нём не вызываются из Win 32 API?
Эти функции вызываются из msvbvm60.dll, т.е. требуют ее наличия, хотя на VB6 их можно сделать собственные. Из winapi нам доступна лишь RtlMoveMemory, еще cdecl memcpy из msvcrt, которую можно использовать с дополнением Трика. На c++ такие функции, конечно можно легко реализовать. Я делаю сейчас такую библиотечку, о чем писалось выше, последнее время я заморочился с вызовами по указателю stdcall/cdecl на VBA (на VB6 это реализуется "средствами языка"). Кое чего выяснил о нюансах экспорта и работы в VS. Чуть позже выложу код, с некторыми пояснениями. Это все так, больше наверное не для пользы, поскольку в наше время, с убыстряющимся развитием нейросетей, уже не знаешь, что может быть полезно, пусть это будет как "хобби" - клепание C++ поделок для VB6/VBA ) Просто интересно чё-нибудь поделать на С++ )

Добавлено через 5 часов 14 минут
Вот, что я придумал для коллбеков по указатею на VBA - сделать множество таких функцийпроцедур-оберток, под разное кол-во аргументов и также множество прототипов под разные сигнатуры вызова (надеюсь, что все это правильно обозвал). В данном случае сделано для stdcall, но в decl вроде бы такая же логика - если функция возвращает значение < 8 байт, то возврат проходит через регистры процессора, если больше, то возврат происходит в скрытый первый аргумент в стеке. Если у кого-то есть другие идеи или замечания пишите.
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
typedef INT64(__stdcall *fun2)(void*, void*);
typedef INT64(__stdcall *fun3)(void*, void*, void*);
typedef void(__stdcall *sub2)(void*, void*);
typedef void(__stdcall *sub3)(void*, void*, void*);
 
void Call2(INT_PTR fn, void* ret, int retSz, void* a1, void* a2) {
    if (ret != NULL) {
        if (retSz <= 8) {
            INT64 ret64 = ((fun2)fn)(a1, a2);
            memcpy(ret, &ret64, retSz);
        }else{
            //вызываем функцию как процедуру если размер возвращаемого значения >8
            ((sub3)fn)(ret, a1, a2); 
        }
    }else{
        // вызываем как процедуру, если это процедура (void)
        ((sub2)fn)(a1, a2);         
    }
}
0
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
02.11.2025, 18:40
Цитата Сообщение от testuser2 Посмотреть сообщение
1) InStr для массивов. Итак, начнем с функции InStr. Не хватает реализации этой функции для массивов, говоря по иному, чтобы функция могла искать блок памияти в другом блоке памяти, реализовать хочу, как поиск любого массива внутри любого массива (не ссылочного ест-но)
Типа такого?
Вложения
Тип файла: zip Проверка.zip (9.8 Кб, 2 просмотров)
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
02.11.2025, 19:07  [ТС]
Argus19, можно лучше кодом, а то, как-то из-за одной плоской функции неохота файлы тягать? )
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
02.11.2025, 19:15  [ТС]
Библиотека с реализованными экспортами некоторых винапи и внутренних функций в т.ч. колбечных хелперов для stdcall и cdecl. Сам проект разросся уже до 700 мб. В основном это файлы самой vs, я хрен ее знает что она там хранит.
Пример использвания
Visual Basic
1
2
3
4
5
6
7
8
9
10
Sub Test_raw_memcmp()
    Dim s1$, s2$, ret&, hLib&, pFun&
    s1 = "Hello world, this is a test"
    s2 = "World"
'    ret = memCmp(ByVal StrPtr(s1) + 12, ByVal s2, LenB(s2))
'    ret = memCpy(ByVal StrPtr(s1) + 12, ByVal s2, LenB(s2))
    hLib = LoadLibW("msvcrt.dll")
    pFun = GetProcAddr(hLib, ToAnsi("memcpy"))
    CCall3 pFun, ret, 4, ByVal s1, ByVal s2, ByVal LenB(s2)
End Sub
В vba в модуле книги лучше прописать
Visual Basic
1
2
3
4
Private Sub Workbook_Open()
    LoadLibraryW StrPtr(ThisWorkbook.Path & "\ATLProject1.dll")
    ChDir ThisWorkbook.Path
End Sub
Вложения
Тип файла: zip ATLProject1.zip (19.0 Кб, 0 просмотров)
0
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
02.11.2025, 19:36
Цитата Сообщение от testuser2 Посмотреть сообщение
можно лучше кодом, а то, как-то из-за одной плоской функции неохота файлы тягат
Проект на VB 6.0 содержит 3 текстовых поля, 2 метки для вывода информации и 4 кнопки.
Проект на С++ состоит из 2 файлов, но занимает 152, 6 Мб.
Проще скачать и запустить.
Реализована (для тренировки) Функция InStr, функция поиска количества вхождений шаблона в строку и функция поиска вхождения шаблона в массив строк.
1
02.11.2025, 20:13

Не по теме:

Цитата Сообщение от Argus19 Посмотреть сообщение
Проект на С++ состоит из 2 файлов, но занимает 152, 6 Мб
Скорее всего это из-за служебных файлов которые можно смело удалить. Папка .vs, *.pch файлы, выходной каталог. Удалите их и сможете выполнить просьбу testuser2 поделиться кодом.

0
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
02.11.2025, 20:39
Цитата Сообщение от OwenGlendower Посмотреть сообщение
Удалите их и сможете выполнить просьбу testuser2 поделиться кодом.
Спасибо за совет. Я и так это сделаю. Сначала надо дописать dll.
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
03.11.2025, 04:21  [ТС]
Вот что я реально ощутил в VS 2017 это нехватку макросов автоматизации (я не нашел как их включть), вроде vba. Как выясняется, в VS были макросы до 2010 версии (взможность записи действий и т.д.) но, в 2012 версии их убрали, и восстановили только в 2022 версии, это странно, целых 10 лет, тогда как, макросы в VS как нельзя кстати. Но как я вижу, работать с файлами проекта можно и по внешке, открываешь в текстовом редакторе, правишь, в VS все автоматически обновляется. Так, что можно с этими файлами работать и из VBA и из чего угодно, одновременно с VS.
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
03.11.2025, 14:13  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
void Call2(
Еще одна реализация, не знаю на сколько быстрая, наверно наоборот медленней, но, просто было интересно сделать в качестве самообразования. Возможно там можно было бы сократить код, используя какие-нибудь лябды. В данном коде можно увидеть использование глобальной переменной - массива с фиксированного размера, в который помещаются указатели функций, выполняющих копирование разного колличества байт. Массив инициализируется в DllMain (т.е. при иницализации библиотеки), и данные в нем сохраняются на протяжении всего сеанса работы с библиотекой. Поскольку для файла dllmain.cpp по умолчанию зада тип запуска cdecl, для иницализирующей функции (initCopyFnArr) задан тип __cdecl (по иному не получалось скомпилировать). Был еще нюанс в том, что данные функции реализованы в файле .с, а initCopyFnArr вызывать надо было в .cpp при этом надо соблюдать определенные тонкости.
Кликните здесь для просмотра всего текста
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
36
37
38
39
40
41
42
typedef struct { unsigned char bytes[3]; } _3B;
typedef struct { unsigned char bytes[5]; } _5B;
typedef struct { unsigned char bytes[6]; } _6B;
typedef struct { unsigned char bytes[7]; } _7B;
void copy0(void* dst, void* src) {}
void copy1(void* dst, void* src) {*(byte*)(dst) = *(byte*)(src);}
void copy2(void* dst, void* src) {*(INT16*)(dst) = *(INT16*)(src);}
void copy3(void* dst, void* src) { *(_3B*)(dst) = *(_3B*)(src); }
void copy4(void* dst, void* src) { *(INT32*)(dst) = *(INT32*)(src); }
void copy5(void* dst, void* src) { *(_5B*)(dst) = *(_5B*)(src); }
void copy6(void* dst, void* src) { *(_6B*)(dst) = *(_6B*)(src); }
void copy7(void* dst, void* src) { *(_7B*)(dst) = *(_7B*)(src); }
void copy8(void* dst, void* src) { *(INT64*)(dst) = *(INT64*)(src); }
typedef void(*copyDlg)(void* dst, void* src);
copyDlg copyFnArr[9];
void __cdecl initCopyFnArr() { //cdecl указан для запуска функции в файле dllmain.cpp для которого по умолчаню задан тип запуска cdecl
    copyFnArr[0] = copy0;
    copyFnArr[1] = copy1;
    copyFnArr[2] = copy2;
    copyFnArr[3] = copy3;
    copyFnArr[4] = copy4;
    copyFnArr[5] = copy5;
    copyFnArr[6] = copy6;
    copyFnArr[7] = copy7;
    copyFnArr[8] = copy8;
}
//__declspec(dllexport)
void Call2_(INT_PTR fn, void* ret, int retSz, void* a1, void* a2) {
    if (ret != NULL) {
        if (retSz <= 8) {
            INT64 ret64 = ((fun2)fn)(a1, a2);
            //memcpy(ret, &ret64, retSz);
            copyFnArr[retSz](ret, ret64);
        }
        else {
            ((sub3)fn)(ret, a1, a2);
        }
    }
    else {
        ((sub2)fn)(a1, a2);
    }
}


Добавлено через 5 минут
Был еще странный затык у меня, долго не мог понять, в чем дело, функции из одного файла, которые ранее нормально работали перестали работать в vba. Как оказалось у этого файла, почему-то в настройках слетел тип stdcall и установился cdecl по умолчанию. Видимо если явно указывать тип запуска для функций гораздо надежнее, но я еще за этим понаблюдаю.. Вообще, я заметил, что в VS периодически могут происходить какие-то странноватые вещи, полностью полагаться на его стабильность наверное нельзя.

Добавлено через 3 минуты
Так выглядит DllMain
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
#ifdef _MERGE_PROXYSTUB
    if (!PrxDllMain(hInstance, dwReason, lpReserved))
        return FALSE;
#endif
    hInstance;
 
    switch (dwReason)   {
    case DLL_PROCESS_ATTACH:
        initCopyFnArr(); // Вызов инициализации при загрузке DLL
        break;
        // Можно добавить очистку при выгрузке, если нужно
    case DLL_PROCESS_DETACH:
        break;
    }
 
    return _AtlModule.DllMain(dwReason, lpReserved);
}


Добавлено через 22 минуты
Цитата Сообщение от Argus19 Посмотреть сообщение
Проект на С++ состоит из 2 файлов, но занимает 152, 6 Мб.
Цитата Сообщение от testuser2 Посмотреть сообщение
Сам проект разросся уже до 700 мб.
Сейчас уже 823 мегобайденов, это не здоровая фигня какая-то )
0
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
03.11.2025, 17:20
Цитата Сообщение от testuser2 Посмотреть сообщение
Сейчас уже 823 мегобайденов, это не здоровая фигня какая-то )
Видимо, проекты хранят не только настройки.
Какие функции работы с массивами строк были бы интересны?
Долго возился с передачей строк в dll. В VB 6.0 строки в формате UTF-16 (BSTR), а в С++ UTF-16 (LPCWSTR).
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
03.11.2025, 19:15  [ТС]
Цитата Сообщение от Argus19 Посмотреть сообщение
Какие функции работы с массивами строк были бы интересны?
Функций много всяких, я одно время заморочился, просматривал какие есть функции на питоне, js, php, делфи и все что нравится, что по проще отбирал и делал на VB, но там много чего не допилено может быть. Вот здесь можете посмотреть. Все эти функции, я в дальнейшем думаю по маленьку затаскивать в сабжевую библиотеку. Еще один момент мне нравился, в том, что на питоне и js целочисленные аргументы работают с отрицательным знаком. Т.е. если бы так был реализован InStr, то при отрицательном значении параметра Start, допустим -5 он бы начинал поиск с 5го символа от конца, это очень удобно, и по возможности я хочу делать также.
Но сейчас мне не до них, какой-то невообразимый затык произошел с файлом idl. Строки которые раньше работали, вдруг стали мешать компиляции, я уже задолбался пересобирать, чтобы сначала их вычислить, потом понять в чем дело, но так и не понял.
C++
1
2
3
4
5
        ////, helpstring("Returns or sets the value of the source string's BSTR pointer. This property allows read/write access to the same value that is returned by Visual Basic's (hidden) StrPtr function.")
        //[entry("GetMemPtr"), propget]
        //HRESULT __stdcall StringPtr([in] BSTR* Src, [out, retval] __int3264* pRetVal);
        //[entry("PutMemPtr"), propput]
        //HRESULT __stdcall StringPtr([in] BSTR* Dst, [in] __int3264 pNewVal);
Вложения
Тип файла: zip IDL.zip (2.0 Кб, 0 просмотров)
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
03.11.2025, 19:32  [ТС]
Вот тоже Instr я недавно делал, очередной, там как раз учитывается отрицательное значение Start. На си конечно можно сделать эффективнее, с указателями и т.д.
VBInstrByt
Visual Basic
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
Private Sub Test_VBInstrByt()
    Dim bWt() As Byte, bWr() As Byte, ret&
    bWr = ToAnsi("sicnoicjjww")
    bWt = ToAnsi("icj")
    ret = VBInstrByt(-11, bWr, bWt)
End Sub
Public Function VBInstrByt(ByVal Start As Long, Where() As Byte, What() As Byte) As Long
    Dim i&, l&, l2&, ubWhat&, ubWhere&, lnWhat&, lnWhere&, What1 As Byte
    
    ubWhat = UBound(What)
    lnWhat = ubWhat + 1
    l2 = lbWhat + 1
    What1 = What(lbWhat)
    ubWhere = UBound(Where)
    lnWhere = ubWhere + 1
    Select Case Start
    Case Is > 0
        If Start < lnWhere Then
        Else: Exit Function
        End If
    Case 0: Start = 1
    Case Else 'если Start < 0 то считаем от конца
        Start = lnWhere + Start + 1
        If Start > 0 Then Else Start = 1
    End Select
    
    For i = Start - 1 To lnWhere - lnWhat
        If Where(i) = What1 Then
            For l = l2 To ubWhat
                i = i + 1
                If Where(i) <> What(l) Then GoTo Nxt
            Next
            
            VBInstrByt = i - lnWhat + 2
            Exit Function
        End If
Nxt:
    Next
End Function


Добавлено через 5 минут
В этой библиотеке я кстати уже 2 строковые функции реализовал
Кликните здесь для просмотра всего текста
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>
BSTR ToAnsi(BSTR str)
{
    if (str == NULL) return NULL;
 
    DWORD size = *((DWORD*)str - 1);
    if (size == 0) return NULL;
 
    int wideLen = size / 2;
 
    int ansiLen = WideCharToMultiByte(CP_ACP, 0, str, wideLen, NULL, 0, NULL, NULL);
    if (ansiLen == 0) return NULL;
 
    BSTR result = SysAllocStringByteLen(NULL, ansiLen);
    if (result == NULL) return NULL;
 
    WideCharToMultiByte(CP_ACP, 0, str, wideLen, (char*)result, ansiLen, NULL, NULL);
    return result;
}
BSTR FromAnsi(BSTR str)
{
    if (str == NULL) return NULL;
 
    DWORD size = *((DWORD*)str - 1);
    if (size == 0) return NULL;
 
    int wideLen = MultiByteToWideChar(CP_ACP, 0, (char*)str, size, NULL, 0);
    if (wideLen == 0) return NULL;
 
    BSTR result = SysAllocStringLen(NULL, wideLen);
    if (result) {
        MultiByteToWideChar(CP_ACP, 0, (char*)str, size, result, wideLen);
    }
    return result;
}
1
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
03.11.2025, 19:36
Цитата Сообщение от testuser2 Посмотреть сообщение
На си конечно можно сделать эффективнее, с указателями и т.д.
Вот именно это и интересно. Т.к. исходники VB до сих пор не утекли в сеть, доработать их невозможно, но вполне возможно написать dll, чтобы упростить код VB и расширить функционал.
Тип std::string в С++ обладает неплохими возможностями.
Цитата Сообщение от testuser2 Посмотреть сообщение
Еще один момент мне нравился, в том, что на питоне и js целочисленные аргументы работают с отрицательным знаком.
Тут уж как кому нравится. В VB поиск начинается с 1, в С++ с нуля:
https://metanit.com/cpp/tutorial/12.6.php
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
03.11.2025, 19:38  [ТС]
Мне с 1 нравится, человеко-читаемо, это по бейсиковски
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
04.11.2025, 05:18  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
какой-то невообразимый затык произошел с файлом idl.
Понял в чем ошибка, я брал эти декларации с vbspeeds, но я там изменил имена аргументов, но это парные property и в них в обоих имя первого аргумента должно быть одинаковым, второй может иметь разное имя.
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
04.11.2025, 13:17  [ТС]
Придумал способ переименовать проект в Visual Studio, так, на заметку
0
1386 / 842 / 91
Регистрация: 08.02.2017
Сообщений: 3,586
Записей в блоге: 1
06.11.2025, 16:34  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
Public Function VBInstrByt
Сегодня часа три пробовал переписать это на C. В итоге фиаско. Дипсик выкатил мне мой исправленный код, который оказался рабочим, но он там напихал временных переменных. Неужели без временных переменных нельзя?
Кликните здесь для просмотра всего текста
Мой код
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
int InStrByt(int Start, SAFEARRAY** Where, SAFEARRAY** What) {
    int cntWhere = (*Where)->rgsabound[0].cElements;
    int cntWhat = (*What)->rgsabound[0].cElements;
    char *pcWhat1 = (char*)(*What)->pvData;
    char *pcWhat2 = pcWhat1 + 1;
    
    if (Start > 0) {
        if (Start < cntWhere) {}else{return 0;}
    }
    else if (Start == 0) {
        Start = 1;
    }
    else {
        Start = cntWhere + Start + 1;
        if (Start > 0) {}else {Start = 1;}
    }
    char *pcWhere = (char*)(*Where)->pvData;
    char *pcEndIter = pcWhere + (cntWhere - cntWhat);
    char *pcEndIter2 = pcWhat1 + cntWhat; //- 1;
    char cWhat1 = *pcWhat1;
    char *pcWhat = 0;
    for(pcWhere = pcWhere + Start - 1; pcWhere <= pcEndIter; pcWhere++) {
        if (*pcWhere == cWhat1) {
            for (pcWhat = pcWhat2; pcWhat < pcEndIter2; pcWhat++) {
                pcWhere++;
                if (*pcWhere != *pcWhat) goto Nxt;
            }
            int ret = (INT_PTR)pcWhere - cntWhat + 1;
            return ret;
        }
    Nxt:;
    }
    return 0;
}
Исправленный код
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
36
37
int InStrByt(int Start, SAFEARRAY** Where, SAFEARRAY** What) {
    int cntWhere = (*Where)->rgsabound[0].cElements;
    int cntWhat = (*What)->rgsabound[0].cElements;
    char *pcWhat1 = (char*)(*What)->pvData;
    char *pcWhat2 = pcWhat1 + 1;  // Исправлено
 
    if (Start > 0) {
        if (Start < cntWhere) {}else{return 0;}
    }
    else if (Start == 0) {
        Start = 1;
    }
    else {
        Start = cntWhere + Start + 1;
        if (Start > 0) {}else {Start = 1;}
    }
 
    char *pcWhere = (char*)(*Where)->pvData;
    char *pcEndIter = pcWhere + (cntWhere - cntWhat);
    char *pcEndIter2 = pcWhat1 + cntWhat;
    char cWhat1 = *pcWhat1;
 
    char *current = pcWhere + Start - 1;  // Временный указатель
    for (; current <= pcEndIter; current++) {
        if (*current == cWhat1) {
            char *search_ptr = current + 1;
            char *pattern_ptr = pcWhat2;
 
            for (; pattern_ptr < pcEndIter2; pattern_ptr++, search_ptr++) {
                if (*search_ptr != *pattern_ptr) goto Nxt;
            }
            return (current - pcWhere) + 1;  // Исправлен расчет
        }
    Nxt:;
    }
    return 0;
}


Добавлено через 1 час 30 минут
Допилил, без лишних временных переменных, надеюсь нет неявных ошибок, и если есть возможно еще как-то дооптимизировать, буду рад
Кликните здесь для просмотра всего текста
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
int InStrByt(int Start, SAFEARRAY** ppSAWhere, SAFEARRAY** ppSAWhat) {
    int cntWhere = (*ppSAWhere)->rgsabound[0].cElements;
    int cntWhat = (*ppSAWhat)->rgsabound[0].cElements;
    char *pcWhere1 = (char*)(*ppSAWhere)->pvData;
    char *pcWhat1 = (char*)(*ppSAWhat)->pvData;
    char *pcWhat2 = pcWhat1 + 1;
    
    if (Start > 0) {
        if (Start < cntWhere) {}else{return 0;}
    }
    else if (Start == 0) {
        Start = 1;
    }
    else {
        Start = cntWhere + Start + 1;
        if (Start > 0) {}else {Start = 1;}
    }
    
    char *pcEndIter = pcWhere1 + cntWhere - cntWhat;
    char *pcEndIter2 = pcWhat1 + cntWhat; //- 1;
    char cWhat1 = *pcWhat1;
    char *pcWhere = pcWhere1 + Start - 1;
    for(; pcWhere <= pcEndIter; pcWhere++) {
        if (*pcWhere == cWhat1) {           
            char *pcWhat = pcWhat2;
            for (; pcWhat < pcEndIter2; pcWhat++) {
                pcWhere++;
                if (*pcWhere != *pcWhat) goto Nxt;
            }
            return (pcWhere - pcWhere1) - cntWhat + 2;
        }
    Nxt:;
    }
    return 0;
}


Добавлено через 2 минуты
Наконец-то узнал, для чего в С-коде часто пишут return 0; оказывается это не заглушка, а реально действующая строка, без нее функция может возвращать какой-нибудь мусор.
1
 Аватар для Argus19
1427 / 444 / 78
Регистрация: 24.09.2017
Сообщений: 2,525
Записей в блоге: 22
06.11.2025, 18:28
Цитата Сообщение от testuser2 Посмотреть сообщение
Наконец-то узнал, для чего в С-коде часто пишут return 0; оказывается это не заглушка, а реально действующая строка, без нее функция может возвращать какой-нибудь мусор.
return возвращаемое значение
Функция может возвращать число или переменную. Может так же, как в libwebp.dll возвращать адрес на массив байт, содержащий символы.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.11.2025, 18:28
Помогаю со студенческими работами здесь

Классы, динамические библиотеки. VB6
Добрый вечер. Ребят, подскажите, никогда не работал с классами в Basic'е. Как работать с классами?...

Не хватает библиотеки
Всем привет. У меня вот такая проблема. Пытаюсь запустить макрос VBA, а он останавливается на...

Подключение нужных библиотек при переносе программы на другой ПК
Всем доброго здоровья! Может ли кто подсказать, как автоматизировать процесс подключения нужных...

Электронные библиотеки или кто откуда качает киниги
Предлагаю создать тему с ссылками на бесплатные электронные библиотеки с книгами по VBA и не только...

Где можно скачать библиотеку чтобы рисовать в VISIO стены, двери или окна
Здравствуйте! где можно скачать библиотеку чтобы рисовать в VISIO стены, двери или окна. И как...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru