java.lang.UnsatisfiedLinkError: Belirtilen prosedür bulunamadı

Nov 16 2020

Bir C ++ DLL'nin JNA sarmalayıcısını geliştirmeye çalışıyorum.

DLL koduna erişimim yok. Bağımlı.exe kullanarak DLL'yi kontrol ettim ve C ++ yöntemleri etrafında bir dekoratör olmadığını gördüm. Ve bu extern "C"da aldığım C ++ * .h dosyasında ayarlanmış gibi görünüyor .

Ama şu hatayı alıyorum:

"Main" iş parçacığında istisna java.lang.UnsatisfiedLinkError: 'compute' işlevi ararken hata: Belirtilen prosedür bulunamadı.

com.sun.jna.Function. (Function.java:252) at com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:600), com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:576) com.sun.jna.NativeLibrary.getFunction (NativeLibrary.java:562) at com.sun.jna.Library$Handler.invoke(Library.java:243) at com.sun.proxy.$Proxy0.compute (Bilinmeyen Kaynak), com.JNA.main (JNA.java:171)

Cpp * .h dosyama bakın:

#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 sarıcımın altına bakın:

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);
}

Böylece test sınıfımda şunları belirledim:

// 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);

Bu nedenle, ortaya çıkan istisnanın benim uygulamamdan değil DLL'den geldiği hissine kapılıyorum. Ancak gönderimin başında iddialarımla ilgili nedenini açıklayacak hiçbir fikrim yok.

  1. Dekoratör ve dışardan beyan sorunu dışında başka bir sebep olabilir mi?

  2. Bağımlı.exe ile DLL incelemesinden extern bildiriminin ayarlandığını nasıl kontrol edebilirim?

@dbwiddis Thanx cevabınız için ancak:

  1. const onun * const girdisi, girdinin sabit bir yapısı üzerinde sabit bir işaretçi olduğu anlamına gelir. Bu, işaretçinin salt okunur bir değerde salt okunur bir parametre olduğu anlamına gelir.

  2. OutputPointer'ı bir dizi olarak ayarladım çünkü onu nasıl kullanacağımdan emin değildim. Aslında başka bir yöntem için bir girdi parametresi olarak buna ihtiyacım var. C ++ için şuna benzer bir şeye sahibim:

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

Böylece jna Sarıcımda var:

public int compute(his input, Pointer[] outputPointer); public int manage(Pointer inputPointer);

Test sınıfımda var:

Pointer[] outputPointer = null;

int resultCompute = compute(input_ref, outputPointer);

int manage(outputPointer[0]);

Her neyse, sizin tavsiyenizi de şu şekilde denedim: Böylece jna Wrapper'ımda var:

public int compute(his input, PointerByReference outputPointer);

public int manage(Pointer inputPointer);

Test sınıfımda var:

PointerByReference outputPointer = null;

int resultCompute = myInterface.compute(input_ref, outputPointer);

int myInterface.manage(outputPointer.getValue());

Ama yine de aynı sorunu yaşıyorum. Hatırlatma olarak, c ++ dll'de tanımlanan yöntem ne olursa olsun, aynı istisnaya sahibim. Gerçekten sorunun jna uygulamamdan kaynaklanmadığını hissediyorum. Ayrıca önemli bir ayrıntı, test sınıfımda dll'nin bir yüklemesini gerçekleştiriyorum:

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);

Yukarıdaki sysout, yani method names = computegörüntülediğim gibi adlandırılan mevcut yöntemin adını gösterir . Kodda hata ayıklarken, yöntem adında bir sorun olduğunu fark ettim. Ancak sysout, jna sarmalayıcımda bildirdiğim yöntemin adını görüntülediğinden, bu yardımcı olmuyor. Henüz c ++ dll'de tanımlanmamış sahte bir yöntemle hızlı bir test yaptım ve aynı hatayı aldım: yordam bulunamadı. Bu yüzden gerçekten o dll ile ilgili bir sorun olduğunu düşünüyorum ama nasıl bulacağımı bilmiyorum ...

Yanıtlar

cknelle Nov 21 2020 at 23:12

Son olarak, sorunumu çözmek için sarmalayıcımı aşağıdaki satırı çağıran java Test ana sınıfıma eklemek zorunda kaldım: System.setProperty ("jna.library.path", "C: \ myWrapper \ src \ main \ kaynaklar"); burada C: \ myWrapper \ src \ main \ resources, dll dosyamın depolandığı klasördür.

Ama aynı klasörde depolanan diğer dll için bu satırı neden ayarlamama gerek olmadığını açıklamıyor, çünkü ortam değişkenlerimde jna.library.path de açıkladım.