Эквивалент C Sharp «public IntPtr pHandle = IntPtr.Zero;» Delphi «hp: Pointer»

1

После некоторых исследований я перевел

pHandle = IntPtr.Zero;

пожаловать в Delphi

var
  pHandle: Pointer; 

Когда я $314328 для отладки в Delphi, я получаю $314328, когда я $314328 для отладки на C sharp, я получаю значение Integer 134180640. Может ли кто-нибудь сказать мне, как сделать правильный перевод в Delphi?

Функция Dll, которую я вызываю в Delphi:

function SAAT_Open(pHandle: Pointer): Boolean; stdcall;

Функция C sharp:

[DllImport("RFIDAPI.dll", EntryPoint = "SAAT_Open")]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool SAAT_Open(IntPtr pHandle);
  • 2
    Ваш перевод верен (и соответствует исходному объявлению C SAAT_Open() ). Проблема в другом месте, например, если вы неправильно инициализируете pHandle .
  • 0
    Я также считаю, что проблема заключается в pHandle, а не в том, как правильно его инициировать. PHandle получает значение после вызова «c # code» if (rbnTCP.Checked) {bInit = RfidApi.SAAT_TCPInit (out pHandle, sReaderIP, iReaderPoint); }
Показать ещё 2 комментария
Теги:
dll
pointers

2 ответа

2
Лучший ответ

После некоторых исследований я перевел

pHandle = IntPtr.Zero;

пожаловать в Delphi

var
  pHandle: Pointer; 

Может ли кто-нибудь сказать мне, как сделать правильный перевод в Delphi?

Синтаксис С# позволяет инициализировать переменную в том же самом заявлении, что вы объявляете переменную:

IntPtr Handle = IntPtr.Zero;

В Delphi вы не можете инициализировать локальную переменную при ее объявлении. Поэтому вам нужно объявить об этом, а затем инициализировать его:

var
  Handle: Pointer;
....
Handle := nil;

Пока вы не назначаете локальную переменную неуправляемого типа, ее значение не определено.


Однако, если вы передадите nil на SAAT_Open тогда он не сработает. Функция ожидает ненулевой дескриптор. Итак, инициализация до nil не поможет вам. Вам нужно сделать больше. Вам нужно вызвать функцию, которая дает новый дескриптор. Это SAAT_TCPInit. Код С#, который вы показываете, который инициализирует дескриптор нулевому значению, делает это без необходимости. Возможно, это так, потому что SAAT_TCPInit был ошибочно переведен для использования параметра ref для дескриптора, а не для правильного перевода, который был бы параметром out.

Хотя приведенное выше отвечает на заданный вами вопрос, это не поможет решить вашу проблему. Вам не нужен нулевой дескриптор, вам нужен фактический дескриптор.


Когда я ломаю для отладки в Delphi, я получаю $ 314328, когда я ломаю для отладки на C sharp, я получаю значение Integer 134180640.

Ну, после pHandle = IntPtr.Zero вы абсолютно не увидите значение 134180640 в С#. Вы увидите значение 0. Должен быть другой код, который инициализирует дескриптор. Предположительно, вызов SAAT_TCPInit. Вам нужно сделать этот звонок. Я верю, что вы это делаете.

Ручка не обязательно будет иметь такое же значение при последующих запусках вашей программы. И не обязательно иметь одинаковое значение в каждой другой программе. На самом деле дескриптор представляет собой динамически выделенный указатель, и его адрес варьируется от одного прогона к другому. Поэтому не стоит беспокоиться о том, меняется ли это, как вы это заметили. Если SAAT_TCPInit возвращает True чтобы указать успех, тогда значение дескриптора будет действительным.

  • 0
    Да, после SAAT_TCPInit указатель получает значение 134180640 или какое-либо другое значение в C #, но когда я делаю то же самое с Delphi, я получаю $ 314328. Не очень понимаю значение знака доллара. Плюс это не активирует тег, как только я делаю SAAT_YTagSelect (hp, isenable, $ 01, sz, 4), где hp - указатель
  • 3
    Я объяснил префикс $ в одном из ваших предыдущих вопросов. Я не понимаю, почему вы не принимаете ответы или не отвечаете на вопросы, которые мы вам задаем. Возможно, вы могли бы просмотреть их все, принять лучшие ответы и по пути узнать о префиксе $ . Я думаю, что я ответил на вопрос, который вы задали здесь. Не могли бы вы сделать мне одолжение и ответить на этот комментарий.
Показать ещё 10 комментариев
3

В.NET IntPtr представляет собой представление типа указателя, которое реализуется под капотом целым числом, потому что оно не может быть фактическим указателем (ссылкой).NET, потому что нужно управлять реальными ссылками. Но это тоже не может быть реальное целое, или вы можете сделать математику на нем, что является хорошим способом получить повреждение памяти. (ПРИМЕЧАНИЕ. Это ограничение может быть или не существовать, в зависимости от того, какая версия С# и/или CLR вы используете.)

Но поскольку вы не можете рассматривать IntPtr как целое число, единственные полезные вещи, которые вы можете сделать с одним, присваивают ему значение, которое вы получаете из другого места, или передаете его на некоторый код, который ожидает IntPtr. IntPtr.Zero существует, чтобы разрешить один отсутствующий, но критически важный сценарий: нулевое значение. Вы не можете назначить ему 0 или протестировать его против 0, и поскольку это не ссылка, вы не можете назначить или протестировать против null. Поэтому они создали его как специальную константу для представления "IntPtr, значение которого равно null".

Если вы хотите сделать эквивалент в Delphi, объявите указатель, а затем инициализируйте его нулем.

  • 1
    Таким образом, эквивалентом IntPtr в Delphi является Pointer (или NativeInt в последних версиях, если вам нужно целое число), а эквивалентом IntPtr.Zero в Delphi является nil (или 0, если используется NativeInt ).
  • 1
    Вы можете выполнить арифметику на IntPtr. А на машинном уровне указатели и целые числа неразличимы.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню