Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > По умолчанию преобразование кода Си в Delphi


Автор: WantToProg 26.4.2009, 12:47
Доброго времени суток уважаемые программисты. В очередной раз хочу вас побеспокоить.
Имеется такой код на Си
Код

unsigned char SendData[] =
            {
                0x1b,'$',
                'H', 'e', 'l', 'l', 'o', ' ',
                'W', 'o', 'r', 'l', 'd',
            };
            MySocketSend(MySocket, SendData, sizeof(SendData));


Работа его заключается в очистке терминала от всех символов и печать на нем текста Hello world.
Все бы ничего, да только надо мне этот код на delphi, а как это сделать, я к сожалению не знаю.
Несколько предположений все таки сделал, но они не работают.
Итак, первое Unsigned Char в Delphi можно представить как Word, ну или Byte. Таким образом получится:
Код

sdbuff: Word;
sdbuff := 0x1b;
Winsock.send(Sock, sdbuff, 256, 0);


Но не понимает Delphi данные в строке sdbuff := 0x1b;, говорит Missing operator or semicolon. То есть не хочет читать данные в шестнадцатиричном представлении.

Я очень прошу подсказать, что я тут не так делаю. Да и вообще, как послать чудо терминалу такую команду? 

Автор: Лапоть 26.4.2009, 12:55
Сишные 0x замени на значок USD - $!
Цитата(WantToProg @  26.4.2009,  13:47 Найти цитируемый пост)
Unsigned Char в Delphi можно представить как Word, ну или Byte

чар - он и в Африке - однобайтовый. Так что вордом он быть никак не может!

Автор: WantToProg 26.4.2009, 13:09
Цитата(Лапоть @  26.4.2009,  12:55 Найти цитируемый пост)
чар - он и в Африке - однобайтовый. Так что вордом он быть никак не может!

Такс, с представлением все ясно. Теперь проблемка с Unsigned Char, если не Word, то что тогда?
Byte - не работает тоже, почему-то посылается непонятный набор символов, а не комманда $1b
Что-то я делаю не так :(

Забыл упомянуть про функцию MySocketSend
Она обрабатывается в другом модуле как:
Код

int MySocketSend(int const Socket, unsigned char const * const Data, size_t const Length)
{
    return send(Socket, Data, Length, 0);
} 


Вопрос в принципе так и остается, как это сделать на Delphi.
Писал его под Linux на Си, теперь надо внедрить в 1С, и есть модуль на  Delphi, вот и пытаюсь что то сделать.

Автор: kami 26.4.2009, 13:31
Код

var
  SendData:string;
begin
  SendData:=#$1b'$Hello World';
  Winsock.send(Sock, SendData[1], Length(SendData), 0);
end;

Автор: WantToProg 26.4.2009, 13:35
kami, Огромное спасибо. Но остался один небольшой вопрос:
Что делать, если вместо текста '$Hello World' должна быть переменная? Как тогда организовать функцию?

по какойто неведомой мне причине 
Код

SendData:=#$1b+str;


Не работает :(

Автор: Keeper89 26.4.2009, 15:17
Вот http://www.delphisources.ru/pages/faq/base/ascii_to_hex.html не поможет? 

Автор: kami 26.4.2009, 16:00
Цитата(WantToProg @  26.4.2009,  13:35 Найти цитируемый пост)
по какойто неведомой мне причине

Причины неведомыми не бывают.
Либо компилятор что-нибудь скажет, либо в run-time ошибка вылезет. Весьма полезно вместо "Аааа, ничего не работает" говорить конкретные причины, например "Компилятор говорит Undeclared identifier: str" или "ESocketError 10061"
Показанный вами код вполне работоспособен.

Еще раз:

Код

procedure SendToTerminal(str:string);
var
  SendData:string;
begin
  SendData:=#$1b+str;
  Winsock.send(Sock, SendData[1], Length(SendData), 0);
end;


Добавлено через 3 минуты и 54 секунды
Цитата(Keeper89 @  26.4.2009,  15:17 Найти цитируемый пост)
Вот это не поможет?

Я еще многого мало знаю, но причем здесь преобразование в Hex представление?

Автор: WantToProg 26.4.2009, 16:40
Цитата(Keeper89 @  26.4.2009,  15:17 Найти цитируемый пост)
Вот это не поможет?  

Не, это тут как бы не при чем.


Цитата(kami @  26.4.2009,  16:00 Найти цитируемый пост)
Причины неведомыми не бывают.
Либо компилятор что-нибудь скажет, либо в run-time ошибка вылезет. Весьма полезно вместо "Аааа, ничего не работает" говорить конкретные причины, например "Компилятор говорит Undeclared identifier: str" или "ESocketError 10061"
Показанный вами код вполне работоспособен.

Да, я согласен с вами, и код работоспособен и ошибок нет. Но вот не очень понятно следущее:
Если я использую: 
Код

SendData:=#$1b'$Hello World';

результат: Hello World - Все понятно, все нормально, команда #$1b, очищает экран
если:
Код

SendData:='#$1b'+str;

результат: #$1b и дальше содержимое переменной. то есть команда воспринимается как набор печатаемых символов, то есть не очищает экран.
А если же:
Код

SendData:=#$1b+str;

результат: только содержимое переменной, команда #$1b почему то игнорируется, т.е. не очищает экран.

В этом и есть суть вопроса. Почему в одной ситуации, без переменной, команда работает, а с переменной нет.

Автор: kami 26.4.2009, 16:51
Поставьте breakpoint на строку Winsock.send(Sock, SendData[1], Length(SendData), 0); и посмотрите, чему равно SendData.

Добавлено через 1 минуту и 10 секунд
Код самой процедуры отправки и процедуры, ИЗ КОТОРОЙ она вызывается в студию.

Добавлено через 7 минут и 52 секунды
Цитата(WantToProg @  26.4.2009,  16:40 Найти цитируемый пост)
если:код Pascal/Delphi1:SendData:='#$1b'+str;

И естественно.
В этом случае к str спереди линкуются 4 символа: #+$+1+b , что само собой ни разу не эквивалентно #$1b

Автор: WantToProg 26.4.2009, 17:19
Цитата(kami @  26.4.2009,  16:51 Найти цитируемый пост)
Поставьте breakpoint на строку Winsock.send(Sock, SendData[1], Length(SendData), 0); и посмотрите, чему равно SendData. 

Это компонента .dll для 1С BP не добавить, поэтому я добавил объект 
Код

MessageBox(0,PChar(SendData),PChar('Exit Program'),MB_ICONINFORMATION+MB_OKCANCEL+MB_DEFBUTTON2);

содержимое SendData = str символом . О чем это может говорить?

Автор: kami 26.4.2009, 17:22
Это может говорить только об одном:
#$1b не добавлено спереди к переменной str.
Или же добавлено, но не к той переменной. (и это вполне серьезно, без иронии).
Цитата(kami @  26.4.2009,  16:51 Найти цитируемый пост)
Код самой процедуры отправки и процедуры, ИЗ КОТОРОЙ она вызывается в студию.


Добавлено через 1 минуту и 3 секунды
Кстати, #$1b выглядит в сообщении, как квадратик.

Добавлено через 10 минут и 22 секунды
Цитата(WantToProg @  26.4.2009,  17:19 Найти цитируемый пост)
BP не добавить

Так внесите логирование через каждую строчку в файл.
"Получили данные для отправки. str='+str
"соединили с символом. SendData='+SendData
"Отправляем SendData. SendData='+SendData

Автор: WantToProg 26.4.2009, 17:42
Цитата(kami @  26.4.2009,  17:22 Найти цитируемый пост)
Кстати, #$1b выглядит в сообщении, как квадратик. 

Да, да. Я просто забыл добавить к переменной. Выглядит именно так.
Таким образом символ #$1b действительно отсылается, но почему то не воспринимается как комманда

Код

var send_sock: TSocket;
var send_string: String;
var send_result: Integer;
var send_ok: Boolean;

procedure send_thread(Param: Integer);
var i:Integer;
begin
  send_ok:=False;


  send_result:=send(send_sock, send_string[1], length(send_string), 0);
  MessageBox(0,PChar(send_string),PChar('Exit Programm?'),MB_ICONINFORMATION+MB_OKCANCEL+MB_DEFBUTTON2);

  if send_result = SOCKET_ERROR then begin
         if WSAGetLastError()=WSAEMSGSIZE then begin        
            for i := 1 to Length(send_string) do begin
              send_result:=send(send_sock, send_string[i], 1, 0);
              if send_result = SOCKET_ERROR then break;
            end;
         end;
  end;
  send_ok:=True;
end;
////////////////////////////////////////////
function send_with_timeout
(s: TSocket; str:String; Timeout: Integer):Integer;
var h1:cardinal;
var i:Integer;
begin
      send_sock:=s;
      send_string:=#$1b+str;
      CreateThread(nil,128,@send_thread,nil,0,h1);
      for i:=1 to Timeout*100 do begin
        sleep(10);
        if send_ok then break;
      end;
      if send_ok=False then TerminateThread(h1,0);
      Result:=send_result;
end;

/////////////////////////////////////////////////
  procedure T_Socket.SendData(s: string);

  begin
    if Connected=False then begin
       Error('Попытка послать данные без подключения к серверу');
    end;
      s:=s+EndOfLine;
      if send_with_timeout(Sock, s, Timeout) = SOCKET_ERROR then begin
           Error('Ошибка отправки данных');
      end;
  end;

Прикрепляю файл на всякий случай, там как раз описан процесс подключения

Автор: kami 26.4.2009, 18:06
Начнем с малого (остальное пока смотрю).
потоковая функция должна быть объявлена как
function send_thread(Parameter: Pointer): Integer; stdcall;. - иногда полезно смотреть исходники Delphi.
Если параметр в данном случае значения не имеет (у integer и pointer размерность одна), то выделенное жирным шрифтом (т.е. отсутствующее у вас - это, извините, очень грубая ошибка).
В дополнение, если работаете с CreateThread в Delphi (хотя это не рекомендуется, безопаснее пользоваться BeginThread), то выставьте хотя бы 
IsMultiThread:=True;

Во-вторых - в корне неверная работа с сокетами (архитектурно, я имею ввиду). Извините, но так писать нельзя. Правда, это тема для отдельной ветки, посему опустим.

У вас есть какой-нибудь сниффер, например http://soft.softodrom.ru/ap/p7531.shtml ?

Если да - посмотрите, что на самом деле отсылаете, потому что других проблем на первый взгляд не видно.

Добавлено через 7 минут и 48 секунд
Почему бы, кстати, не воспользоваться ClientSocket вместо всей этой возни с WinSock?
Было бы гораздо проще и нагляднее...

Добавлено через 9 минут и 27 секунд
Цитата(WantToProg @  26.4.2009,  17:42 Найти цитируемый пост)
Таким образом символ #$1b действительно отсылается, но почему то не воспринимается как комманда

А он воспринимается как команда сразу после приема получателем, или после того, как получателю дойдут CRLF -символы ?

Автор: WantToProg 26.4.2009, 18:16
Все, огромное спасибо, проблема решена. На самом деле, нужно было немного включить мозг. Спешка мешает серьезно.

Код

send_string:=#$1b+str;

 нужно было добавить '$' таким образом
Код

send_string:=#$1b'$'+str;


И все заработает.

Цитата(kami @  26.4.2009,  18:06 Найти цитируемый пост)
Начнем с малого (остальное пока смотрю).
потоковая функция должна быть объявлена как
function send_thread(Parameter: Pointer): Integer; stdcall;. - иногда полезно смотреть исходники Delphi.
Если параметр в данном случае значения не имеет (у integer и pointer размерность одна), то выделенное жирным шрифтом (т.е. отсутствующее у вас - это, извините, очень грубая ошибка).
В дополнение, если работаете с CreateThread в Delphi (хотя это не рекомендуется, безопаснее пользоваться BeginThread), то выставьте хотя бы 
IsMultiThread:=True;

Во-вторых - в корне неверная работа с сокетами (архитектурно, я имею ввиду). Извините, но так писать нельзя. Правда, это тема для отдельной ветки, посему опустим.

У вас есть какой-нибудь сниффер, например WireShark ?

Если да - посмотрите, что на самом деле отсылаете, потому что других проблем на первый взгляд не видно. 


Я был бы не прочь посмотреть другие варианты работы с сокетами. Просто в Delphi пишу первый раз и первую программу.
Да если честно, вообще опыта не много. Учусь так сказать smile

Автор: kami 26.4.2009, 18:19
Цитата(WantToProg @  26.4.2009,  18:16 Найти цитируемый пост)
нужно было добавить '$' 

"Я ш откедова  знала-то" smile что $ - это еще один управляющий символ smile

Удачи !

Автор: WantToProg 26.4.2009, 18:22
Цитата(kami @  26.4.2009,  18:06 Найти цитируемый пост)
А он воспринимается как команда сразу после приема получателем, или после того, как получателю дойдут CRLF -символы ? 

Данные отсылаются на сканер штрих кодов, а как он работает я понятия не имею. Все вычислял эмпирическим путем, т.е. наугад.

Цитата(kami @  26.4.2009,  18:19 Найти цитируемый пост)
"Я ш откедова  знала-то" smile что $ - это еще один управляющий символ

Да я сам понятия не имел smile

Благодарю за помощь, но чувтствую не последний раз спрашиваю

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)