Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Внутри C++ кода есть. Код: plaintext 1. В какой-то момент ей присваивается реальная строка: Код: plaintext 1. Эту строку UserName надо отфутболить через API в VB6 приложение Пытаюсь так например: Код: plaintext 1. 2. 3. 4. 5. Вот как это правильно сделать? Доставать пытаюсь так: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. Не получается строку прочитать, пусто! По хорошему на стороне VB конструкция должна быть примерно такая: Код: vbnet 1. 2. 3. 4. 5. 6. 7. Но я не понимаю как зарядить эту конструкцию на стороне C++. C аналогичными ф-циями где надо вернуть несколько чисел (а не строку) я разобрался. Например: C++ Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. VB6 Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. С int/Long все работает. Помогите мне char * из C++ вытащить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 02:55 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Все оказалось немного проще: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. К счастью на VB6 я собаку с доставанием строки по Ptr-указателю давно съел. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 03:35 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77, а просто вернуть BSTR (размещённый через SysAllocString) ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 04:40 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Изопропил, Я рад что у меня хоть как то получилось. А чем char * плох? Asprotect в своих API использует именно char *, его я и возвращаю через мою API. А VB6 по любому получит Long - указатель (Ptr) на начало строки. А конец строки - нулевой символ. Проблема возникла из того, что в VB6 нельзя напрямую вызвать нормальные API AsProtect. Вот здесь чуть подробнее: Вопрос по API ф-циям AsProtect если кто сталкивался или умеет использовать "сложные" API. Зато dll-ки с API писать научился. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 06:57 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77А чем char * плох? кто память освобождать будет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 09:29 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Изопропил, а ты ссылку смотрел постом выше, где более менее полный код приведен? Конструкция Код: plaintext 1. 2. 3. 4. 5. 6. навязана из документации AsProtect. (верхняя "API" не моя и она сработает автоматом, моя (вызываемая по требованию из VB6) только нижняя) А AsProtect фиг знает чего там делает и чего освобождает. Или считаешь, что я должен что-то освобождать со стороны VB, я же только отдаю ссылку на память, а значение там и так лежит с момента как сработает dll (LoadLibrary?) И полагаю что то что там создается при выгрузке dll (проги) очищается. Или предлагаешь коверкать типы? Оно стоит? Я и так C++ коды в час по чайной ложке рожаю. В любом случае UserName запрашивается один раз при старте программы и памяти много не занимает (даже если согласиться что она таки теряется). А почему так уверен что теряется? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 09:57 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77Внутри C++ кода есть. Код: plaintext 1. Возможно это будет интересно: в разных C++ компиляторах NULL может иметь разное значение, а не 0, как это можно было бы ожидать, что может привести к неожиданному результату для конструкций вида Код: plaintext 1. Поэтому лучше присваивать либо 0, либо nullptr (для C++11). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 11:54 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
CompositumВозможно это будет интересно: в разных C++ компиляторах NULL может иметь разное значение, а не 0, как это можно было бы ожидать, что может привести к неожиданному результату для конструкций вида Код: plaintext 1. Какие могут быть неожиданности, если оператор отрицания для указателей возвращает отрицание сравнения с NULL? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:00 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77а ты ссылку смотрел постом выше, где более менее полный код приведен? есть прямой путь Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:08 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovКакие могут быть неожиданности, если оператор отрицания для указателей возвращает отрицание сравнения с NULL?[/quote] А что тут непонятного? Если символическая константа NULL равна 0, то результат проверки будет 1. В противном случае результат проверки будет 0. Т.о. в зависимости от реализации компилятора результат приведённой мною выше проверки может оказаться различным. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:09 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
CompositumА что тут непонятного? Если символическая константа NULL равна 0, то результат проверки будет 1. В противном случае результат проверки будет 0. Т.о. в зависимости от реализации компилятора результат приведённой мною выше проверки может оказаться различным.Ещё раз !указатель == !(указатель == NULL) Поэтому (если вдруг), найдётся компилятор, где NULL !== 0 - всё будет работать корректно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:13 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovЕщё раз Код: plaintext 1. Поэтому (если вдруг), найдётся компилятор, где NULL !== 0 - всё будет работать корректно. Исходный код: Код: plaintext 1. Если записывать в такой форме: Код: plaintext 1. то несомненно, это всегда будет работать правильно, вне зависимости от реализации компилятора. Но если записать в таком виде: Код: plaintext 1. то возникнет ситуация, о которой я писал выше, поскольку если в реализации конкретного компилятора символическая константа NULL окажется не равной 0, то указанное вами равенство Код: plaintext 1. окажется неверным, т.к. Код: plaintext 1. вернёт 0, в то время как Код: plaintext 1. вернёт 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:25 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Compositumвернёт 1.Рассматривайте части моего "равенства" как уравнение и всё встанет на свои места. P.S. А вы можете привести пример компилятора, где NULL !== 0? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:28 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovРассматривайте части моего "равенства" как уравнение и всё встанет на свои места. Не вижу, каким образом? Basil A. SidorovP.S. А вы можете привести пример компилятора, где NULL !== 0? Я пользуюсь только MS Visual Studio и GNU g++. А что, обязательно нужно ждать, чтобы споткнуться об это? То, что упоминалось мною выше взято не с потолка, а было вычитано из книжек, где и было дано предупреждение о том, что не стоит слепо полагаться на то, что в C++ всегда NULL == 0, т.к. это не регламентировано в стандарте, но отдано на откуп разработчиков компиляторов. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 12:48 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Вспомнил один из сточников, где читал подобного рода информацию: Стивен Прата, "Язык программирования C++ (C++11). Лекции и упражнения", 6-е издание. Глава 12, стр. 610, примечание "Нулевой указатель в C++11". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:04 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
CompositumТо, что упоминалось мною выше взято не с потолка, а было вычитано из книжекА в этих книжках не пояснялась семантика оператора "boolean not" применительно к указателям? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:05 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovCompositumТо, что упоминалось мною выше взято не с потолка, а было вычитано из книжекА в этих книжках не пояснялась семантика оператора "boolean not" применительно к указателям? Насколько мне известно, оператор "!" превращает 0 в 1, а любое число, отличное от 0 превращает в 0. Поправьте меня, если я не прав. Я что, где-то выше противоречил этому? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:10 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Compositum, Вы слишком все упрощаете. Оператор ! (а также if() и т.п.) создает булевый контекст для своего аргумента. В булевом контекте, число 0 неявно приводится к false, остальные числа к true. Для указателя другое правило: NULL приводится к false, остальные указатели к true. Таким образом, какое бы не было физическое значение у нулевых указателей, конструкция !ptr всегда работает корректно. Теперь про обратную сторону. Compositum Код: plaintext 1. вернёт 1. Это опять упрощение. Оператор ! не возвращает 0 или 1. Он возвращает bool, т.е. false или true. А в числовом контексте (например при присвоении в int), эти значения неявно переводятся в их соответствующие числовые представления, 0 или 1 (насколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:27 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Anatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1 быстрый гуглинг показал, что при преобразовании из bool в int по стандарту обязательно приводятся к 0 или 1. Но это не отменяет все остальное что я говорил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:32 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyДля указателя другое правило: NULL приводится к false, остальные указатели к true. Спасибо, учту на будущее. Я думал, что и указатели приводятся к bool на основе числового значения адреса, на который они указывают. Anatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать любое число, отличное от 0 трактуется как true (из книжек). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:53 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
CompositumЯ думал, что и указатели приводятся к bool на основе числового значения адресаА ведь вам намекали. Долго. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:55 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Basil A. SidorovА ведь вам намекали. Долго. Мне лучше писать прямо, без намёков, поскольку надлежащего опыта программирования в C++ у меня нет. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 13:56 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
CompositumAnatoly Moskovskyнасколько я помню стандартом не определено что true это именно 1, но могу ошибаться, т.к. нет времени искать любое число, отличное от 0 трактуется как true (из книжек). CompositumМне лучше писать прямо, без намёков Пишу вам прямо, без намёков - я там в процитированном пишу про перевод из bool в числа. А вы написали про обратное преобразование. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.07.2013, 14:04 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
ИзопропилДмитрий77а ты ссылку смотрел постом выше, где более менее полный код приведен? есть прямой путь Код: plaintext 1. 2. 3. 4. 5. Хорошо, давай вообще без самодурства. Есть пример несамодурной API: GetWindowText function Код: plaintext 1. 2. 3. 4. 5. Код для использования GetWindowText из VB6 простой и понятный: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Заметь, без использования моей САМОДУРНОЙ PtrToString на стороне VB6. при помощи которой я вытаскиваю String из памяти зная только Ptr. И я пытаюсь создать свою API по образу и подобию GetWindowText (чтоб возвращала длину и заполняла буфер строчкой). Делаю так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Достаю так: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. MsgBox length -честно возвращает число "5" А вот MsgBox RegInfo ни фига не возвращает (буфер как был пуст, так и остался). Что я не так написал в dll что у меня буфер строчкой не заполняется? Как реализовать _Out_ LPTSTR lpString Я в C-шном коде выделил места подвоха. Ток вот как правильно я не знаю. Поможете? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 20:55 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77И я пытаюсь создать свою API по образу и подобию GetWindowText (чтоб возвращала длину и заполняла буфер строчкой). Делаю так: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. Что я не так написал в dll что у меня буфер строчкой не заполняется? Как реализовать _Out_ LPTSTR lpString Я в C-шном коде выделил места подвоха. Ток вот как правильно я не знаю. Поможете? Ты не заполняешь буфер, а переопределяешь его. Строки в С это массивы. Их надо копировать специальными функциями, простому знаку равенства они не подвластны. Код: plaintext 1. 2. 3. 4. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 21:27 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White Owl Код: plaintext 1. 2. 3. 4. 1>.\LicenseDll.cpp(73) : error C2664: 'strncpy' : cannot convert parameter 1 from 'LPTSTR' to 'char *' 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 21:42 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77 Как реализовать _Out_ LPTSTR lpString без фокусов получать BSTR* а передавать byref as string ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 21:42 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77White Owl Код: plaintext 1. 2. 3. 4. 1>.\LicenseDll.cpp(73) : error C2664: 'strncpy' : cannot convert parameter 1 from 'LPTSTR' to 'char *' 1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style castДай угадаю, у тебя включен UNICODE режим и ты компилируешь в С++? Выключи первое в настройках проекта. И переименуй свой исходник в .c для выключения второго. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 22:01 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
бейсик конвертит свои юникодные строки в ANSI и обратно при вызове функций из dll чтоб избавиться от геморроя можно вернуть из dll единственный объект (IDispatch) и далее просто вызывать его методы и обращаться к свойствам ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.07.2013, 22:36 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White Owl, 1) Юникод я отключил в Property Pages -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions Снял галку Inherit from parent or project defaults где что-то про это говорилось Надеюсь это касается только тек. проекта и не "испортит" компилятор? В принципе мне Юникод не нужен и в VB6 я например борюсь со случайными его "проявлениями". Это когда len(String) вдруг начинает выдавать невменяемое значение после какого-нибудь strconv(,vbUnicode). 2) Файл в .c переименовывать не стал 3) Заменил Код: plaintext 1. на Код: plaintext 1. (как присоветовал компилятор, читать Warning! допустимо, но не особо приятно) Ничего не попутал, два раза воткнув именно nMaxCount (а не lenth напр.)? Короче, к коду ниже претезии есть? Память чиста? Совесть чиста? Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Все работает. И плюс свел ф-цию к стандартному приему используемому в VB6. У меня и первый вариант с char * работал, но Вам не понравилось. Я бы забил, но мне хотелось привести к "стандарту". Мой PtrToString это не тривиально и не стандарт, и я ее написал в прошлом году исключительно потому, что с Opal с его ветвящимися структурами из ссылок на const char * по другому из VB6 работать не получилось. Просто у вас в C++ тут очень интересно. Какая то дурацкая строчка с NULL вызывает бурные дискуссии на неделю вперед. Мало того что 5 строчек кода высасываются из пальца 2 дня, так тебе еще неделю объясняют про 10 других способов. Вот нафига мне этот IDispatch? Работать с IЧтонибудь из VB6 ой как нелегко, если только не через tlb-обертку. Не, я делал Windows Audio API (это которые New), но в VB6 с этим повеситься можно, но пришлось это сделать т.к. Вистовские миксеры со старыми multimedia API глючат. В данном случае никакой необходимости IИздеватьсяНадСобой нету. Просто ответьте. Последний вариант безупречен? Если В НЕМ что не так то что? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 00:25 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
А по поводу Код: plaintext 1. на который все так дружно набросились, Ну если dll не "защищена", то NULL там так и останется, соотв. вызов API элементарно вызовет crash. Я думаю вариант Код: plaintext 1. лучше подойдет для инициализации, не так ли? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 00:39 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77White Owl, 1) Юникод я отключил в Property Pages -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions Снял галку Inherit from parent or project defaults где что-то про это говорилось Надеюсь это касается только тек. проекта и не "испортит" компилятор? В принципе мне Юникод не нужен и в VB6 я например борюсь со случайными его "проявлениями". Это когда len(String) вдруг начинает выдавать невменяемое значение после какого-нибудь strconv(,vbUnicode). Нет, это не испортит компилятор. Просто ты используешь LPSTR в своем проекте. Это собственный микрософтовский "тип" данных который является синонимом либо char*, либо unsigned short *. В первом случае ты будешь работать с обычной ASCIIz строкой, во втором с двухбайтовыми строками. И надо будет вместо strncpy использовать функцию wstrncpy. Первый случай это без UNICODE флага, второй случай с ним. Дмитрий772) Файл в .c переименовывать не сталТы в любом случае вынужден писать верхний уровень на С. Потому что VB не способен импортировать С++ классы и методы классов. Поэтому у тебя весь исходник и обернут в extern "C" блок. Если у тебя имя исходного файла some.cpp, то extern "C"{} обязателен. Если some.c, то не обязателен. На мой взгляд, если тебе нет нужды использовать классы и/или чьи-то С++ библиотеки, то проще писать сразу на С. Дмитрий773) Заменил Код: plaintext 1. на Код: plaintext 1. (как присоветовал компилятор, читать Warning! допустимо, но не особо приятно) Ничего не попутал, два раза воткнув именно nMaxCount (а не lenth напр.)? Вообще-то попутал. nMaxCount относится к lpString, но не имеет никакого отношения к UserName. Дмитрий77Короче, к коду ниже претезии есть? Память чиста? Совесть чиста? Есть претензии. Если ты используешь strncpy_s, то и обработку ошибок делай соответствующую. Вот так получше будет: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 00:59 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White OwlВообще-то попутал. nMaxCount относится к lpString, но не имеет никакого отношения к UserName.ну и что? он же обрезает результирующую строку, если length <= nMaxCount, а больше в неё не попадёт по определению. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 01:22 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
egorych, хотя твой вариант красивее, согласен. замучали меня под вечер абстракциями своими в программировании, прости ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 01:24 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77А по поводу Код: plaintext 1. на который все так дружно набросились, Ну если dll не "защищена", то NULL там так и останется, соотв. вызов API элементарно вызовет crash. Я думаю вариант Код: plaintext 1. лучше подойдет для инициализации, не так ли?Нет, так не будет лучше ни в коем случае. Пойми одну простую вещь: В С и С++ нету строк. Вообще нету. Никаких. По определению. Любая запись типа кавычки-буковки-кавычки это на самом деле объявление константного массива который будет содержать указанные буковки и конечный ноль. Каждый массив лежит где-то в памяти. А чтобы программа знала где это самое "где-то" находится существуют "указатели". В Бейсике указатели тоже существуют, но они "спрятаны под капотом". Единственный случай когда ты сталкиваешься с указателями в VB это когда объявляешь параметр функции ByRef. А в С и С++ указатели используются намного шире и любая работа со строками в С это на самом деле манипулирование указателем на массив символов. Объявляя char* name ты объявляешь не массив, а четыре байтика в памяти (для 32х битного приложения). В эти четыре байтика ты можешь записать реальный адрес в памяти где будет лежать настоящий массив. Например запись: char* UserName = ""; Объявляет массив размером в один байт (только один конечный нолик) и кладет этот массив в специальный сегмент памяти называемый сdata. Потом выделяет в сегменте памяти data четыре байтика (обзывает эти четыре байтика UserName) и записывает в них адрес одно-байтового массива. Если ты теперь в коде функции сделаешь: UserName="John"; то на самом деле, ты объявил в сегменте cdata массив из пяти байт и проинициализировал его четырьмя буквами и одним нулем, причем это произошло еще до старта программы. А во время выполнения функции ты перенаправляешь указатель UserName на этот пятибайтовый массив. При этом однобайтовый массив ты теряешь. Окончательно и бесповоротно. До того начального массива ты уже никогда-никогда не доберешься. Запись типа char* UserName = NULL; намного лучше. В данном случае ты создаешь указатель (те самые именованные четыре байтика), но вместо адреса реального массива ты пишешь туда "стандартное" значение. Потом его можно использовать для проверки задан UserName или нет. Например тебе надо вызывать функцию несколько раз, но проинициализировать только однажды: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. Теперь сколько бы раз ты ни вызывал init() операция присвоения UserName выполнится только однажды. Это не очень показательный пример, но если UserName читается не из другой переменной а например из базы данных, или из сети, или спрашивается у юзера, то подобный трюк с начальным NULL может здорово облегчить жизнь. Если же просто объявить char *UserName; То ты создашь в памяти переменную в которой будет какое-то случайное значение. И этот пример работать уже не будет. Ты можешь заметить что использованный в примере NULL можно запросто заменить на какой-нибудь UNDEFINED. И будешь прав. Но в этом случае ты сам должен будешь создать UNDEFINED, в то время как NULL обычно уже существует и все про него знают и показанные трюки считаются нормой жизни. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 01:40 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77Вот нафига мне этот IDispatch? Работать с IЧтонибудь из VB6 ой как нелегко, если только не через tlb-обертку. не путайте IDispatch и IЧтонибудь IDispatch - это бейсиковый Object с поздним связыванием, никакого tlb не требуется ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 02:11 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White Owl, Код: plaintext 1. Я не понимаю какую ты ошибку пытаешься отловить в errno_t rc, 1) если будет length > nMaxCount-1 то будет crash без всякой ловли. 2) А любое значение между lenth и nMaxCount-1 к crash не приводит и дает корректный результат 3) Если считаешь что все-таки правильно инициализировать Код: plaintext 1. Сложно спорить с такими доводами, и не буду. Но если при вызове API там будет NULL то будет crash. Посему думаю чем отлавливать ошибки (до отлова которых дело не дойдет) проще руководствуясь здравым смыслом писать код чтоб их не было. Я переделал вот так и жду замечаний: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. Можно конечно заменить на Код: plaintext 1. 2. 3. 4. 5. 6. 7. но особого смысла в этом не вижу. Благодаря возврату "честной" длины я могу чуть модифицировать VB6 код и получать полную необрезанную строку максимум в 2 итерации: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Ну, или довольствоваться обрезанной пользуясь предыдущим кодом Код: vbnet 1. 2. Т.е. левая часть длиной 540 от заполненного буфера [255]+\0 выдаст безошибочно строку длиной 255 (т.е. vb-шный код не ошибется). С Вами не соскучишься. Чувствую, если писать все на C++ то и программу не напишешь, и денег не заработаешь (такими то темпами). Но зато умным человеком станешь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 04:14 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77Благодаря возврату "честной" длины я могу чуть модифицировать VB6 код и получать полную необрезанную строку максимум в 2 итерации в традициях WINAPI при передаче NULL в качестве адреса буфера возвращается (через результат или выходной параметр) необходимый размер ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 08:10 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Изопропилв традициях WINAPI при передаче NULL в качестве адреса буфера возвращается (через результат или выходной параметр) необходимый размер Не всегда. Извращаются как хотят. Например GetPrivateProfileString Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Return value The return value is the number of characters copied to the buffer, not including the terminating null character. If neither lpAppName nor lpKeyName is NULL and the supplied destination buffer is too small to hold the requested string, the string is truncated and followed by a null character, and the return value is equal to nSize minus one. If either lpAppName or lpKeyName is NULL and the supplied destination buffer is too small to hold all the strings, the last string is truncated and followed by two null characters. In this case, the return value is equal to nSize minus two. Поэтому здесь мой вариант VB6 кода с 2-мя итерациями уже не пройдет. Пользуюсь вот таким кодом: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. На практике обычно задается большой буфер (в предположении что места хватит) и никаких проверок не производится. Для моей ф-ции которую здесь мусолим такого варианта вполне достаточно. Но я несколько раз накалывался с этим, в частности с ini-файлом, поэтому (с учетом на будущее) все таки хочу написать подобную штуку "с запасом прочности". Кстати я в своем крайнем варианте еще не проверял что будет если nMaxCount=0 т.е. Код: plaintext 1. Скрашит небось. А с другой стороны если знаешь API изнутри, или есть нормальное описание в msdn или где-то там которое внимательно читаешь, то никогда не будешь вызывать API с недозволенными параметрами. А вариант безусловного применения Код: plaintext 1. как раз может скрашить 1) если UserName=NULL 2) если length > nMaxCount - 1 и этот краш определяется значением UserName, т.е. вызывающая сторона не виновата что какой-то идиот засунул в Username строку в 10000 символов например. И вот это уже не есть гуд. Я неправ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 16:17 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77White Owl, Код: plaintext 1. Я не понимаю какую ты ошибку пытаешься отловить в errno_t rc, http://msdn.microsoft.com/en-us/library/5dae5d43(v=vs.80).aspx Читай внимательно описание функции. Все что ты делаешь сравнивая length и nMaxCount - не нужно. Это все уже встроено внуть strncpy_s. Читай документацию. Дмитрий771) если будет length > nMaxCount-1 то будет crash без всякой ловли.не будет. Читай документацию. Дмитрий772) А любое значение между lenth и nMaxCount-1 к crash не приводит и дает корректный результатНет. Читай документацию. Дмитрий773) Если считаешь что все-таки правильно инициализировать Код: plaintext 1. Сложно спорить с такими доводами, и не буду. Но если при вызове API там будет NULL то будет crash.Нет, не будет. Читай документацию. Дмитрий77Посему думаю чем отлавливать ошибки (до отлова которых дело не дойдет) проще руководствуясь здравым смыслом писать код чтоб их не было.Да, конечно, лучше писать чтобы их не было. И я тебе уже показал как должен выглядеть код использующий функцию strncpy_s(). Дмитрий77Я переделал вот так и жду замечаний:Плохо. Все плохо. У тебя 90% кода - бессмысленная работа. А обработки ошибок нет вообще. Дмитрий77С Вами не соскучишься. Чувствую, если писать все на C++ то и программу не напишешь, и денег не заработаешь (такими то темпами). Но зато умным человеком станешь.А если ты наконец решишься прочитать любой учебник по С (я советую K&R) и поймешь работу с указателями, а потом не будешь лениться читать документацию на используемые функции то все будет легко и замечательно. А до тех пор будешь писать фигню. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 21:25 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White OwlДмитрий771) если будет length > nMaxCount-1 то будет crash без всякой ловли.не будет. Читай документацию. Дмитрий772) А любое значение между lenth и nMaxCount-1 к crash не приводит и дает корректный результатНет. Читай документацию. Дмитрий773) Если считаешь что все-таки правильно инициализировать Код: plaintext 1. Сложно спорить с такими доводами, и не буду. Но если при вызове API там будет NULL то будет crash.Нет, не будет. Читай документацию. Вот ты говоришь не будет (Should NOT согласно документации). А я говорю что крашит (ИЗЪ ЕСМЬ что вижу то и докладываю). Почему тогда у меня твой код (с обработкой ошибок) генерит crash при вызове в указанных случаях? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 21:38 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77Почему тогда у меня твой код (с обработкой ошибок) генерит crash при вызове в указанных случаях? Так мы ж не видим код, который вы запускаете. Может у вас там проблема в других местах. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 21:44 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77White Owlпропущено... не будет. Читай документацию. пропущено... Нет. Читай документацию. пропущено... Нет, не будет. Читай документацию. Вот ты говоришь не будет (Should NOT согласно документации). А я говорю что крашит (ИЗЪ ЕСМЬ что вижу то и докладываю). Почему тогда у меня твой код (с обработкой ошибок) генерит crash при вызове в указанных случаях? Если согласно документации should not, а в реальность is - значит одно из двух: либо документация врет, либо ты делаешь неправильно. Проверяется это очень просто: Отложи в сторону свой существующий супер-проект. Сделай новый примитивный проект в котором попытайся повторить проблему. Если проблему повторить на микро-проекте удастся - опубликуй его здесь. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 21:58 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
White OwlСделай новый примитивный проект в котором попытайся повторить проблему. Так это и есть микропроект. На стороне C одна функция (ну пусть 2-3 аналогичных, но дергаю то одну) На стороне VB6 декларация ф-ции + код одной кнопки. Anatoly MoskovskyТак мы ж не видим код, который вы запускаете. Значит плохо смотрите, если не видите: 14513598 Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Для получения crash с кодом предложенным White Owl выполнить этот код вполне достаточно для указанных двух случаев: 1) NULL 2) lenth > nMaxCount- 1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 22:09 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
А в "свой существующий супер-проект" я пока что вставил код из второго поста: 14502889 который у меня сомнений в надежности не вызывает. И кстати, как люди говорят, 14518605 , ZVIПравильно было сделано в начале, во 2-м сообщении, с возвратом 2-байтного указателя на начало строки. ...А память там освобождать и не нужно было, потому что исходная С-ная строка не модифицируется, а создается копия строки в VB, и возвращаемый указатель там используется только для копирования С-шной строки в другую VB-строку. Единственное, почему я так прицепился к последнему варианту, потому что он "стандартизирован" и не предполагает побайтное рытье памяти на стороне VB6, что очень нестандартно хотя и работает железно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 22:21 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77, почему не вернуть без фокусов BSTR или VARIANT? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 23:24 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
ИзопропилДмитрий77, почему не вернуть без фокусов BSTR или VARIANT? Да ради бога. Ты предлагал: Код: plaintext 1. 2. 3. 4. 5. По сути это ничем не отличается от возврата char *. Кроме пристрастий и сомнительных споров про память (лично я окончательно судить не берусь, но человек - цитата чуть выше -говорит что все там с памятью нормально) А так напишешь? Код: plaintext 1. 2. Или даже так? Код: plaintext 1. 2. Ну, ты понимаешь к чему я клоню. К стандартизированному методу вызова. Чтоб скопировать результат в буфер длиной nMaxCount и вернуть lenth. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 23:40 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77, в случае возврата BSTR нет никакой нужды в передаче длины строки и прочих танцев с бубном с буфером ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 23:48 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Всем -привет! Давненько я не брал в руки C-шашек! Обычно механизм возврата строки из С в VB такой: Код С-dll Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Код VB: Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Приложил cpp, dll и VB проектик ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.07.2013, 23:52 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
ZVIОбычно механизм возврата строки из С в VB такой: тебе рассказать, что такое переполнение буфера или сам нагуглишь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 00:34 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Изопропилтебе рассказать, что такое переполнение буфера или сам нагуглишь? Спасибо, не нужно :) За небрежность C кода извиняюсь. И malloc и free для string здесь, конечно же, были бы уместны. И не нужно рассказывать про то, что Strncpy сама не допускает переполнения, а VB, в отличие от C, сам за собой подчищает память, кроме объектных переменных, конечно (не наш случай). А со стороны VB, если посмотрите, разумные для примера меры приняты. Если бы я делал для себя, то передавал бы из VB в DLL и/или обратно только указатель на начало строки, чтобы исключить преобразования из 2 байтных в однобайтные массивы и обратно. Подробнее написал там: 14519739 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 01:34 |
|
||
|
Как мне написать API-ф-цию чтоб возвращала строку.
|
|||
|---|---|---|---|
|
#18+
Дмитрий77Для получения crash с кодом предложенным White Owl выполнить этот код вполне достаточно для указанных двух случаев: 1) NULL 2) lenth > nMaxCount- 1 1) NULL Вы так горячо спорили про этот самый NULL. Но ни один из вас даже намеком не обмолвился что нельзя делать strlen (NULL) и именно эта строчка и дает crash Проверяйте, Код: plaintext 1. 2. 3. этого например достаточно чтоб вылететь в мир иной Надо хотя бы ЭТО проверять. Код: plaintext 1. 2. 3. 2) lenth > nMaxCount- 1 Что касается strncpy _s то что бы там не было в документациях, при конструкции Код: plaintext 1. она извините ругается МАТОМ а не ошибкой в errno_t rc как видимо следует из документации. А вот вариант Код: plaintext 1. очень даже проходной с этой точки зрения. Компилятор чего-то там бурчит, но ведь компилирует, и программа дух не испускает. Честно говоря к чертям этот nMaxCount, толку от него никакого, да и он нуль-терминаторов честно говоря тоже, length то известна, мусор по-любому отсекается на уровне приложения. Посему вот так в самый раз: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Код: vbnet 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. ИзопропилДмитрий77, в случае возврата BSTR нет никакой нужды в передаче длины строки и прочих танцев с бубном с буфером Да, спасибо. Я оценил наконец. Код: plaintext 1. 2. 3. 4. 5. 6. 7. Код: vbnet 1. 2. 3. 4. 5. 6. 7. 8. 9. Черт, никогда ранее не видел чтобы API ф-ция в VB6 ВОЗВРАЩАЛА As String Круто. ZVI, спасибо за поддержку. Как мне все это надоело. Оставлю наверно свой вариант из второго поста. Вполне себе рабочий вариант такой и уже вставлен в проект. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.07.2013, 04:42 |
|
||
|
|

start [/forum/topic.php?all=1&fid=57&tid=2020106]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
78ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
72ms |
get tp. blocked users: |
2ms |
| others: | 294ms |
| total: | 489ms |

| 0 / 0 |
