java.lang.Uns พอใจLinkError: ไม่พบโพรซีเดอร์ที่ระบุ
ฉันกำลังพยายามพัฒนา JNA wrapper ของ C ++ DLL
ฉันไม่สามารถเข้าถึงรหัสของ DLL ฉันตรวจสอบ DLL โดยใช้ depend.exe และฉันเห็นว่าไม่มีมัณฑนากรรอบ ๆ วิธีการ C ++ และดูเหมือนว่าextern "C"จะถูกตั้งค่าในไฟล์ C ++ * .h ที่ฉันดึงมา
แต่ฉันมีข้อผิดพลาดต่อไปนี้:
ข้อยกเว้นในเธรด "main" java.lang.Uns SatisfiedLinkError: เกิดข้อผิดพลาดในการค้นหาฟังก์ชัน 'คำนวณ': ไม่พบโพรซีเดอร์ที่ระบุ
ที่ com.sun.jna.Function. (Function.java:252) ที่ com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:600) ที่ com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:576) ที่ com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:562) ที่ com.sun.jna.Library$Handler.invoke(Library.java:243) at com.sun.proxy.$Proxy0.compute (ไม่ทราบแหล่งที่มา) ที่ com.JNA.main (JNA.java:171)
ดูไฟล์ cpp * .h ของฉัน:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct s_mine
{
e_color color; //e_color is enum type made of int values
his data;
int str;
unsigned int wild;
unsigned int hello;
float rice;
} mine;
typedef struct s_his
{
unsigned char * data;
unsigned int size;
} his;
// compute function which raised the exception
int compute(const his* const input, void ** outputPointer);
// treat function raised also the same exception
int treat(const mine* inputParameter, mine* outputParameter);
#ifdef __cplusplus
}
#endif
ดูด้านล่างกระดาษห่อ JNA ของฉัน:
public interface MyInterface extends Library {
@FieldOrder({"data", "size"})
public static class his extends Structure {
public static class ByReference extends his implements Structure.ByReference {}
public static class ByValue extends rt_buffer implements Structure.ByValue {}
public Pointer data;
public int size;
}
@FieldOrder({"color","data","str","wild","hello","rice"})
public class mine extends Structure {
public static class ByReference extends mine implements Structure.ByReference {}
public int color;
public his data;
public int str;
public int wild;
public int hello;
public float rice;
}
public int compute(his input, Pointer[] outputPointer);
public int treat(mine inputParameter, mine outputParameter);
}
ดังนั้นในชั้นเรียนการทดสอบของฉันฉันตั้งค่า:
// COMPUTE
MyInterface.his.ByReference input_ref = new MyInterface.his.ByReference();
ByteBuffer init_buffer;
// init_buffer is initialized with some not null values
Pointer init_p = Native.getDirectBufferPointer(init_buffer);
input_ref.data = init_p;
input_ref.size = init_buffer.capacity();
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
// TREAT
MyInterface.mine.ByReference inputParameter_ref = new MyInterface.mine.ByReference();
MyInterface.his.ByValue buffer = new MyInterface.his.ByValue();
// initialize buffer with an input buffer value different from null value
// Set other fields of inputParameter_ref with none null values
inputParameter_ref.data = buffer;
MyInterface.mine.ByReference outputParameter_ref = null;
int resultTreat = treat(inputParameter_ref, outputParameter_ref);
ดังนั้นฉันจึงรู้สึกว่าข้อยกเว้นที่เพิ่มขึ้นไม่ได้มาจากการใช้งานของฉัน แต่มาจาก DLL แต่ฉันไม่มีเงื่อนงำใด ๆ ที่จะอธิบายว่าเหตุใดเกี่ยวกับการยืนยันของฉันในตอนต้นของโพสต์ของฉัน
อาจมีเหตุผลอื่นนอกจากมัณฑนากรและปัญหาการประกาศภายนอกหรือไม่?
ฉันจะตรวจสอบได้อย่างไรว่ามีการตั้งค่าการประกาศภายนอกจากการตรวจสอบ DLL ด้วยขึ้นอยู่กับ.exe
@dbwiddis Thanx สำหรับการตอบกลับของคุณ แต่:
const ของเขา * const อินพุตหมายความว่าอินพุตเป็นตัวชี้ค่าคงที่ในโครงสร้างของเขาคงที่ ซึ่งหมายความว่าตัวชี้เป็นพารามิเตอร์แบบอ่านอย่างเดียวบนค่าแบบอ่านอย่างเดียว
ฉันตั้งค่า outputPointer เป็นอาร์เรย์เพราะฉันไม่แน่ใจเกี่ยวกับวิธีการใช้งาน แน่นอนฉันต้องการมันเป็นพารามิเตอร์อินพุตสำหรับวิธีอื่น สำหรับ c ++ ฉันมีบางอย่างเช่น:
int compute(const his* const input, void ** outputPointer); // **outputPointer is an output of compute method
int manage(void * inputPointer); // As *outputPointer becomes an input of manage method
ดังนั้นฉันจึงมีใน jna Wrapper ของฉัน:
public int compute(his input, Pointer[] outputPointer); public int manage(Pointer inputPointer);
ในชั้นเรียนทดสอบของฉันฉันมี:
Pointer[] outputPointer = null;
int resultCompute = compute(input_ref, outputPointer);
int manage(outputPointer[0]);
อย่างไรก็ตามฉันลองทำตามคำแนะนำของคุณดังนี้: ดังนั้นฉันจึงมีใน jna Wrapper ของฉัน:
public int compute(his input, PointerByReference outputPointer);
public int manage(Pointer inputPointer);
ในชั้นเรียนทดสอบของฉันฉันมี:
PointerByReference outputPointer = null;
int resultCompute = myInterface.compute(input_ref, outputPointer);
int myInterface.manage(outputPointer.getValue());
แต่ฉันยังคงมีปัญหาเดิม เพื่อเป็นการเตือนความจำไม่ว่าวิธีการใดที่กำหนดไว้ใน c ++ dll ฉันมีข้อยกเว้นที่เพิ่มขึ้นเหมือนกัน ฉันรู้สึกจริงๆว่าปัญหาไม่ได้มาจากการใช้งาน jna ของฉัน รายละเอียดที่สำคัญในชั้นทดสอบของฉันฉันทำการอัปโหลด dll:
Map options = new HashMap();
options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() {
public String getFunctionName(NativeLibrary library, Method method) {
System.out.println("method names = "+method.getName());
return super.getFunctionName(library, method);
}
});
MyInterface myInterface = (MyInterface) Native.load("dllName",MyInterface.class,options);
sysout ด้านบนแสดงชื่อของเมธอดปัจจุบันซึ่งเรียกว่าเช่น I have method names = computeแสดง การดีบักโค้ดฉันสังเกตเห็นว่ามีปัญหากับชื่อวิธีการ แต่เนื่องจาก sysout แสดงชื่อของเมธอดที่ฉันประกาศใน jna wrapper ของฉันจึงไม่เป็นประโยชน์ ฉันเพิ่งทำการทดสอบอย่างรวดเร็วด้วยวิธีการปลอมซึ่งไม่ได้กำหนดไว้ใน c ++ dll และฉันมีข้อผิดพลาดเดียวกัน: ไม่พบขั้นตอน ดังนั้นฉันคิดว่ามีปัญหากับ dll นั้นจริงๆ แต่ฉันไม่รู้จะหาได้อย่างไร ...
คำตอบ
สุดท้ายฉันต้องเพิ่มในคลาสหลักของ java Test ซึ่งเรียก wrapper ของฉันในบรรทัดต่อไปนี้เพื่อแก้ปัญหาของฉัน: System.setProperty ("jna.library.path", "C: \ myWrapper \ src \ main \ resources"); โดยที่ C: \ myWrapper \ src \ main \ resources คือโฟลเดอร์ที่เก็บไฟล์ dll ของฉัน
แต่ไม่ได้อธิบายว่าทำไมฉันไม่จำเป็นต้องตั้งค่าบรรทัดนี้สำหรับ dll อื่นที่เก็บไว้ในโฟลเดอร์เดียวกับที่ฉันประกาศ jna.library.path ในตัวแปรสภาพแวดล้อมของฉันด้วย