2015-04-09 2 views
2

Я использую C++ DLL через JNA. Я хочу вызвать следующий метод в Java, который записывает в szVisor информацию, которую я хочу прочитать.JNA: EXCEPTION_ACCESS_VIOLATION

long FAR PASCAL DLL_GetLocalPortTS(char* szEquip,char* szVisor){ 
    ... 
} 

Реализация интерфейса Java заключается в следующем:

public interface IE2E extends Library { 
    // Instancia de la dll, carga la librería 
    IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class); 
    ... 
    int GetLocalPortTS(String equip, String[] equipInfo); 
} 

и метод вызова:

String equip = "equipID"; 
String equipInfo = ""; 
String[] rEquipInfo = {equipInfo}; 
IE2E sdll = IE2E.INSTANCE; 

int ret = sdll.GetLocalPortTS(equip, rEquipInfo); 

Это исполнение сетками мне фатальную ошибку в JRE, но если я ставлю как аргументы как String или String [], это не так. Однако, если я использую обе строки, это не перезаписывает equipInfo, и я не получаю информацию, которую я хочу; если я использую как массивы, метод не получает значение экипировки и не работает.

Любое понимание этого приветствуется.

+0

Если 'PASCAL' оценивает' __stdcall', вам необходимо реализовать 'StdCallLibrary' (в противном случае это может привести к сбою). – technomage

ответ

2

Проблема в том, что код C хочет записать в szVisor, правильно? Я предполагаю, что это делает что-то вроде этого:

long GetLocalPortTS(char* szEquip,char* szVisor){ 
    strcpy(szVisor, "I am C code result :)"); 
    return 0; 
} 

Если вы передаете в строку со стороны Java, то память принадлежит JVM, поэтому запись на него вызывает сбой. Вам нужен объект Memory, который представляет собой завернутый бит памяти malloc'd, который код C может безопасно записать.

Ваш новый интерфейс JNA будет следующим. Я заметил старую версию, так что вы можете сравнить:

public interface IE2E extends Library { 
    IE2E INSTANCE = (IE2E) Native.loadLibrary("e2e", IE2E.class); 
    //int GetLocalPortTS(String equip, String[] equipInfo); 
    int GetLocalPortTS(String equip, Memory equipInfo); 
} 

И код для вызова он будет выглядеть следующим образом, то 256 является заполнителем. Убедитесь, что вы выделить достаточно записать строку:

String equip = "equipID"; 
String equipInfo = ""; 
//String[] rEquipInfo = {equipInfo}; 
Memory rEquipInfo = new Memory(256); 
IE2E sdll = IE2E.INSTANCE; 
int ret = sdll.GetLocalPortTS(equip, rEquipInfo); 

Чтобы использовать результат в виде строки, вы могли бы сделать это:

rEquipInfo.getString(0); 

Как сказано в документации, finalize() метод Запоминающее устройство автоматически вызывает бесплатно в памяти malloc'd, поэтому нет необходимости беспокоиться о утечке памяти.

+0

Мне раньше удавалось встраивать String в массив, поэтому я думал, что использование памяти не понадобится. В любом случае, вы просто попали в точку. Спасибо огромное! – DSalas

Смежные вопросы