Несогласованные результаты при вызове DLL из JNA/C по сравнению с Pascal

У меня есть библиотека DLL С++ с предоставленными файлами заголовков без реализации. И я реализую вызов JNA для функций этой библиотеки. А у меня проблема только с 1 функцией (другая, даже похожая работает нормально). Это объявление из файла .h:

int CALLINGCONV SMIMESignML(
  const char* pin,
  unsigned long slot,
  const char* szOutputFilePath,
  const char* szFrom,
  const char* szTo,
  const char* szSubject,
  const char* szOtherHeaders,
  const char* szBody,
  const char* szAttachments,
  unsigned long dwFlags,
  int bInitialize
);

Java-код:

public interface Dll extends StdCallLibrary {
  public String JNA_LIBRARY_NAME = "libname.dll";
  int SMIMESignML(String pPin, int slot, String pOut, String pFrom, String pTo,
    String pSubject, String pHeaders, String pBody, String pAttachments, int flags,
    int init);
}

public class Test {
  private static final Dll dll = (Dll) Native.loadLibrary(Dll.JNA_LIBRARY_NAME, Dll.class, W32APIOptions.ASCII_OPTIONS);

  public static void main(String[] args) {
    String pOut = "";
    String pFrom = "";
    String pTo = "";
    String pBody = "";
    String pAttachments = "";

    int code = dll.SMIMESignML(null, 0, pOut, pFrom, pTo, null, null, pBody, pAttachments, 0, 0);
    System.out.println(code);
  }
}

Функция должна возвращать разные коды ошибок типа int, но всегда возвращает код 0xFFFF.

Я могу проверить это тем же кодом на Паскале:

unit dll;
interface
const
  JNA_LIBRARY_NAME = 'libname.dll';

function SMIMESignML(pPin: PChar; slot: integer; pOut: PChar; pFrom: PChar; pTo: PChar;
  pSubject: PChar; pHeaders: PChar; pBody: PChar; pAttachments: PChar; flags: integer;
  init: integer): integer; stdcall; external JNA_LIBRARY_NAME;
implementation
end.

program Hello;
uses dll;
var 
  code: integer;
begin
  code := SMIMESignML(nil, 0, '', '', '', nil, nil, '' , '', 0, 0);
  writeln(code);
end.

Код Pascal возвращает 2, код Java возвращает 65535. Более того, вызовы Pascal std работают правильно, изменяя аргументы, мы получаем разные коды ошибок (0=OK и другие), но Java с теми же аргументами не работает, он всегда возвращает 0xFFFF. Как я могу отладить его, чтобы понять проблему?

P.S. Более того, в этой же библиотеке у меня есть эта функция и она без проблем работает из JNA:

int CALLINGCONV PKCS7SignML(
  const char *pin,
  unsigned long slot,
  const char* szInputFileName,
  const char* szOutputFileName,
  int bInitialize);

ОС Win8 x64, JavaOracle7x86, библиотека x32. «unsigned long» не должно быть проблемой, так как в Windows оно должно быть 4 байта.

Что я делаю неправильно, если один и тот же вызов STD возвращает разные результаты в этих двух примерах? И как я могу отладить это?


person Dmitrii Stebliuk    schedule 16.07.2015    source источник
comment
Я не уверен, что это повлияет на это, но я считаю, что int на 64-битной версии на самом деле будет 8 байтов. int32_t гарантирует 4 байта.   -  person Richard    schedule 16.07.2015
comment
Может ли функция C возвращать -1?   -  person Richard    schedule 16.07.2015
comment
Функция C возвращает только положительные числа, 0 - УСПЕХ, › 0 какой-то код ошибки, 0xFFFF - неизвестная ошибка.   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
если я предоставляю Java long для unsigned long - я получаю ошибку памяти. Библиотека x32-битная, и кажется, что длина без знака составляет 4 байта. Пробовал NativeLong вместо Java int, но результат тот же, что и с int.   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
Обратите внимание, что это C, а не C++   -  person technomage    schedule 16.07.2015
comment
Используйте String напрямую, а не возитесь с памятью и буферами, JNA сделает перевод за вас.   -  person technomage    schedule 16.07.2015
comment
Спасибо, я попробую использовать String, это может упростить код, но я не уверен, что это проблема. Потому что я пытался загрузить и вызвать это из C++, и получил ту же проблему, что и в JNA - функция всегда возвращает 0xFFFF и не работает. Я попытался обернуть рабочий код Pascal собственной DLL без параметров, и когда я использую его с JNA, он не работает... (но все еще работает в Pascal)...   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
Нет, использование String не является причиной. Что может меня отличать, так это то, что паскаль по-разному продвигает возвращаемое значение. Это похоже на 16-битное значение -1, которое может быть вполне допустимым кодом возврата.   -  person technomage    schedule 16.07.2015
comment
@Richard native long составляет 32 бита в 32- и 64-битных ОС. Большинство других операционных систем сопоставляют собственный тип long с размером указателя.   -  person technomage    schedule 16.07.2015
comment
Если вызов из C возвращает одно и то же значение, то с JNA проблем нет, поскольку они используют один и тот же механизм для выполнения вызовов.   -  person technomage    schedule 16.07.2015
comment
@technomage Да. Эта функция считывает ключ со смарт-карты, создает файл и подписывает его ключом. Код Pascal с другими атрибутами возвращает код 0=OK, и файл создается. Код JNA и C всегда возвращает 0xFFFF, и ничего не происходит. В этом простейшем примере Паскаль возвращает 2=смарт-карта не инициализирована. Так вот в чем проблема: одна и та же stdlib с одинаковыми параметрами ведет себя по-разному в Java и Pascal.   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
Идентичны ли ваши входные данные в случаях Java/C и Pascal?   -  person technomage    schedule 16.07.2015
comment
@technomage Да, конечно. Похоже, что в случае с Java/C код не выполняется, как будто какое-то исключение генерируется в самом начале, и возвращается неизвестный код ошибки...   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
@technomage И проблема не в параметрах, потому что я создал dll на Паскале без каких-либо входных параметров, которые вызывают эту функцию с жестко заданными значениями. Когда я вызываю новую функцию без параметров из JNA, она возвращает мне тот же 0xFFFF и ничего не происходит. Если я делаю это из Pascal, он возвращает 0=Ok и создает подписанный файл...   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
Какой код ошибки вы получаете при вызове через JNA с параметрами real? Очевидно, вам нужно было хотя бы дать вашему вызову из паскаля действительное имя файла, чего вы не делаете в вызове JNA.   -  person technomage    schedule 16.07.2015
comment
@technomage Например: эти параметры действительны ('12345678', 0, 'C:\myfolder\email.eml', '', '', nil, nil, '' , '', 0, 1), и это возвращает 65536 в JNA и 0=Ok в Pascal (и создается вызов из файла pascal email.eml).   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
@technomage Последний параметр означает автоматическую инициализацию смарт-карты, в примере вопроса это 0, поэтому мы получаем error_code = 2 (NOT_INITED). Если мы укажем для него 1, не указывая пин (первый параметр), код Pascal выдает ошибку памяти, в то время как код Java работает без ошибок и просто возвращает 65535, как всегда.   -  person Dmitrii Stebliuk    schedule 16.07.2015
comment
Возможно, есть какой-то код автоинициализации для библиотеки, которая вызывается только при загрузке из контекста Паскаля? Используйте Dependency Walker, чтобы узнать, есть ли другие экспортированные методы инициализации/деинитировки.   -  person technomage    schedule 16.07.2015
comment
@technomage offtop: я пытался использовать строку вместо указателя для поля PIN, длина PIN-кода составляет 8, указатель создается с длиной 10, и после этого функция изменения всегда возвращает мне код ошибки, неверный PIN-код. С указателем работает. Поэтому я думаю, что не могу использовать строки вместо указателей.   -  person Dmitrii Stebliuk    schedule 17.07.2015
comment
Это потому, что вы используете W32API.DEFAULT_OPTIONS, который использует широкие (Unicode) строки (wchar_t* в нативном). Вместо этого вам нужно использовать ASCII_OPTIONS.   -  person technomage    schedule 17.07.2015
comment
@technomage Это работает, спасибо!   -  person Dmitrii Stebliuk    schedule 17.07.2015
comment
Я только что понял, что неправильное сопоставление строк также повлияет на данные, которые видит DLL, что может привести к другому коду ошибки. ASCII_OPTIONS решил вашу другую проблему? Однако это не объясняет, почему C не удается получить доступ.   -  person technomage    schedule 17.07.2015
comment
@technomage К сожалению, нет   -  person Dmitrii Stebliuk    schedule 17.07.2015