Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 25.01.2012, 00:52   #1
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию Передать wchar_t* из Си dll в Делфи приложение.

Есть Си длл, в ней экспортированная функция:
Код:
extern "C" void __declspec(dllexport) Test(wchar_t* str)
{
	str = L"test";
}
В Делфи пытаюсь произвести вызов таким образом:
Код:
...
procedure Test(out str: PWideChar); cdecl; external 'MyDLL.dll';
...
procedure TForm1.Button1Click(Sender: TObject);
var
  s: PWideChar;
begin
  Test(s);
end;
Но результат не самый лучший - "Точка входа в процедуру...и т.д.". Видимо типы параметров в Делфи не совсем правильные. Кто что может подсказать?
А и сама цель всего этого - из длл вернуть текст через параметр.
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 25.01.2012, 01:16   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

1)так как вы не используете def файл, то имя скорее всего не то что вы ожидаете.
проверьте сначало.
2)неверно написана процедура, она в принцице ничего не вернет, нужно или применять strcpy.
или же можно просто вернуть указатель на вашу строку.
3)так же неверно описание процедуры в Делфи.
4)ну и вызов неверен.
как бы делал я.
С++,длл:
Код:
//допустим данные в неком std::wstring data, и могут меняться

int __stdcall Test(wchar_t* buffer, int bufferlength)//stdcall больше мне по душе, 
//но мой вам совет, указывайте всегда явно соглашение вызова
{
    if(bufferlength>=data.size()+1)
        wcscpy(str,);
    return data.size()+1;
}
экспорт через def-файл, иначе можете долго гадать с именем.

в Делфи:
Код:
procedure Test(buffer: PWideChar;bufflength:integer); stdcall; external 'MyDLL.dll';

function Test:string;//и пишем оберточку удобную:)
begin
 SetLength(Result,Test(nil,0));
 Test(@Result[1],Length(Result)+1);
end;
как то так
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 25.01.2012, 23:29   #3
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Так...с этим все ясно, спасибо.
Но все же остался еще один вопрос - а с одним параметром нельзя никак провернуть это дело? Ну что бы вот как-то так:
Код:
int __stdcall Test(wchar_t* buffer)
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 25.01.2012, 23:33   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

можно, но не стоит, ошибкостойкость(точнее возможность минимизировать ошибки) кода снижаете.

хотя, у вас в ДЛЛ константа или же изменяемое значение?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 25.01.2012, 23:57   #5
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Цитата:
хотя, у вас в ДЛЛ константа или же изменяемое значение?
По сути там и то, и другое. Т.е. при нормальном исходе работы функции - возвращается динамическое(ну т.е. изменяемое значение), а вот если что-то пошло не так - нужно вернуть предопределенные строковые константы). Вот и хочется как-то привести к вызову с одним параметром.

Цитата:
можно, но не стоит
А все же можете уточнить?
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 26.01.2012, 18:21   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

подход с одним параметром приведет к тому, что мы не будем знать размер буфера, и будем тупо копировать данные по указателю, соответственно если вызывающий ждал 5символов, а мы скопируем 10, то будет ошибка.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.01.2012, 19:37   #7
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

spamer

А все же можете уточнить?

подход, который ты практикуешь, страдает уязвимостью к переполнению буфере, который является проблемой безопасности #1. Главная же опасность для программиста заключается в том, что в нормальных конторах таких быстро отстреливают.
Rififi вне форума Ответить с цитированием
Старый 27.01.2012, 00:50   #8
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Rififi, не верно мыслите, ибо вот такой способ мне действительно не нужен, когда не известно рухнет приложение или нет...Поэтому вобщем-то и спрашиваю совет...
Тут вот что еще подумал - известно, что данные не смогут превышать определенный размер N (т.е. меньше может быть, но не больше), тогда ведь можно объявить константу под размер буфера, например Nmax байт и независимо от того, какой размер данных(т.е. это сформированная строка или предопределенная), передавать всегда Nmax байт.
Вроде вариант нормальный, хотя может чего-то не учел. Что можете сказать по этому поводу?
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 27.01.2012, 00:59   #9
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Код:
const int N=255;//длина именно данных

int __stdcall Test(wchar_t* buffer)//stdcall больше мне по душе, 
//но мой вам совет, указывайте всегда явно соглашение вызова
{
    buffer[N]=0;//терминал ставим явно.
    wcsncpy(str,data.c_str(),N);
    return data.size();//возвращаем реальную длину данных
}

Код:
procedure Test_import(buffer: PWideChar); stdcall; external 'MyDLL.dll' name 'Test';

function Test:string;//и пишем оберточку удобную:)
const N:integer=255;
begin
 SetLength(Result,N);
 SetLength(Result,Test_import(@Result[1]);
end;
вполне удобно помоему выходит.
проблемы с переполнением исключены, и раз вы сами можете поставить эти рамки то код вас ничем не ограничивает.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 27.01.2012, 01:04   #10
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Значит решено. Как раз последний вариант меня устраивает.
Пепел Феникса, спасибо.
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
передать в параметре путь для сохранения файл[консольное приложение] Snake22 Visual C++ 1 19.01.2012 20:43
wchar_t под linux => wchar_t под windows hard-t Qt и кроссплатформенное программирование С/С++ 0 28.10.2011 17:57
Как передать адрес метода из dll в приложение и присвоить его событию OnClick? puga555 Общие вопросы Delphi 1 22.12.2009 17:04
Как передать путь на файл в приложение? evgenrpo Общие вопросы .NET 5 20.11.2009 23:08
Как передать POST data через запрос в веб-приложение Anticrim Java для Web (EE, Servlet, JSP, Tomcat, Spring MVC) 3 03.10.2007 18:19