0

I am developing a web application using jsf, spring and hibernate. This application is similar to other web sites like money.rediff.com and finance.yahoo.com. Our company has made a deal with a realtime data provider. He provided a exe file which on installing generates a dll file, pdf listing the methods of dll file and other license documents.

I used dependency walker and found that the methods are decorated with some symbols. I am trying to call the methods of dll file with the help of JNA in the following way.

Here are my codes,

DllImplementation .java

public interface CLibrary extends StdCallLibrary
    {
       CLibrary INSTANCE = (CLibrary) Native.loadLibrary("DeskApi", CLibrary.class, new 

HashMap() {{

              put("Initialise", "?

Initialise@CDeskApi@@QAEHPADPAVCDeskApiCallback@@@Z");
              put("GetQuote","?GetQuote@CDeskApi@@QAEHPADHKK@Z");
              put("DeleteQuote","?DeleteQuote@CDeskApi@@QAEHPADH@Z");
              put("VersionInfo","?VersionInfo@CDeskApi@@QAEHPAD@Z");

              //Other functions
              }});

    public int Initialise(String serialkey,CDeskApiCallback callBack);
    public int GetQuote(String symbol, int periodicity, long lasttimeupdate, long 

echo);
    public int DeleteQuote(String symbol, int periodicity);
    public int VersionInfo(String versionOut);

    }




    public static  void main(String argv[]) {

            try{

                CDeskApiCallback callback = new CDeskApiCallback();

                String key = "fsg@xxxxxxxxxxxxxxxxxxxxd24";

                int retValue = CLibrary.INSTANCE.Initialise(key,callback);

                System.out.println("Initialise () ="+retValue);  




             } catch (UnsatisfiedLinkError e) {

                 e.printStackTrace();
             }
        }
}

CDeskApiCallback.java

public class CDeskApiCallback {


    public  native int realtime_notify(String symbol, Pointer recent);
    public  native int quote_notify( String symbol, int interval, int nMaxSize, 

    Pointer quotes, long echo);

}

Quotation.java

public class Quotation  extends Structure implements Structure.ByReference{ 
    public NativeLong DateTime; // 8 byte
    public float   Price;
    public float   Open;
    public float   High;
    public float   Low;
    public float   Volume;
    public float   OpenInterest;

    public Quotation(){
       super();
       System.out.println("in Quotation()");
       read();
    }

}

RecentInfo.java

public class RecentInfo extends Structure  implements Structure.ByReference{

    public  float   fOpen;
    public  float   fHigh;
    public  float   fLow;
    public  float   fLast;
    public  float   fTradeVol;
    public  float   fTotalVol;
    public  float   fOpenInt;
    public  float   fPrev;
    public  float   fBid;
    public  float   fAsk;
    public  int     iBidSize;   
    public  int     iAskSize;
    public  NativeLong  DateTime;

    public RecentInfo(){
        super();
        read();
        }

}

To test the code when I execute the main method I am getting a -1 as a integer return value. From the pdf of software providers it indicates as an error. How can i implement the callback mechanism.

I am new to JNA feature . Any clue or help will be highly appreciable.


Edit:

@manuell

First of all thanks for the help. I made the changes as advised but no use. I am pasting the header file given by the software provider. Please suggest...

#pragma once
//version 0.0 Beta 1
#define DAILY_PERIOD 24*60
#define MIN_PERIOD   1

#ifdef API_DLL 
#define METHOD_TYPE __declspec(dllexport)
#else
#define METHOD_TYPE __declspec(dllimport)
#endif
//data is provided in the struct below
struct Quotation {
                        unsigned long DateTime; // 8 byte
                        float   Price;
                        float   Open;
                        float   High;
                        float   Low;
                        float   Volume;
                        float   OpenInterest;                       
                 };

struct RecentInfo
{
    float   fOpen;
    float   fHigh;
    float   fLow;
    float   fLast;
    float   fTradeVol;
    float   fTotalVol;
    float   fOpenInt;
    float   fPrev;
    float   fBid;
    int     iBidSize;
    float   fAsk;
    int     iAskSize;
    unsigned long DateTime; // 8 byte   
};

//callback class which is to be implemented by the client application
class METHOD_TYPE CDeskApiCallback
{
    public:
        /*
        Description : Tick Update from the server for symbol requested
        Parameters  : 1. symbol of interest
                      2. Data, please note value -1 indicates no update.
        Return      : 0 in case of success and -1 in case of error  
        */  
    virtual int realtime_notify(const char* symbol, RecentInfo *pRecent)=0;
        /*
        Description : Vwap Update from the server for symbol requested
        Parameters  : 1. symbol of interest
                      2. update of interval requested
                      3. data size
                      4. data
                      5. user message
        Return      : 0 in case of success and -1 in case of error  
        */  
    virtual int quote_notify( const char* symbol, int interval, int nMaxSize, Quotation *pQuotes, unsigned long echo)=0;    
};

//this is the control class from which requests are initiated.
class  METHOD_TYPE CDeskApi
{
public:
    CDeskApi(void);

        /*
    Description : Initiates a connection to NEST system
    Parameters  : 1. serialkey provided to implement the api
                  2. object of CDeskApiCallback implemented

    Return      : 0 in case of success and -1 in case of error  
        */  
    int Initialise(char *serialkey, CDeskApiCallback* callback);
        /*
        Description : Request data from the server
        Parameters  : 1. symbol of interest
                      2. intervals of 1 min, multiples of 1 min, DAILY_PERIOD in case of daily.
                      3. data to be retrieved from. in no of seconds since epoch
                      4. identifier, which is returned in the callback          
        Return      : 0 in case of success and -1 in case of error  
        */  

    int GetQuote(char * symbol, int periodicity, unsigned long lasttimeupdate, unsigned long echo);
        /*
        Description : Delete a Prior Request to the server
        Parameters  : 1. symbol of interest
                      2. interval, send -1 to delete all requested information of the symbol 
        Return      : 0 in case of success and -1 in case of error  
        */  
    int DeleteQuote(char * symbol, int periodicity);
        /*
        Description : Delete a Prior Request to the server
        Parameters  : 1. symbol of interest
                      2. interval, send -1 to delete all requested information of the symbol 
        Return      : 0 in case of success and -1 in case of error  
        */  
    int VersionInfo(char * versionout);
    ~CDeskApi(void);
};
Wanna Coffee
  • 2,742
  • 7
  • 40
  • 66
  • You can't just pass a Java `String` to a C/C++ function. and your callbacks should inherit from `Callback`. See http://stackoverflow.com/q/10158582/1374704 and http://stackoverflow.com/q/11849595/1374704 – manuell Jan 23 '14 at 11:52
  • I have edited my question, please have a look at it. – Wanna Coffee Jan 24 '14 at 06:57
  • I am not fluent in JNA. It appears that you can indeed use the Java String class to call a native function expecting a C char* argument. Sorry for telling you otherwise. – manuell Jan 24 '14 at 10:27

1 Answers1

2

The native DLL is a C++ one, exporting classes.

That means, for example, that the Initialise method is a "*this" method.

That also means that the callback argument (second one from Initialize) should be a pointer to a VTBL (as the C++ CDeskApiCallback class is an abstract one).

You may be able to deals with the two problems using the Java Pointer type, but that will be tricky hacks. By default, the rules are clear: you can't use JNA in a C++ classes context.

You are left with 3 choices (plus the tricky one):

  1. try to use Bridj
  2. try to use jnaerator
  3. write yourself a C++ Dll Wrapper and use it from JNA (or JNI).

The third one involves basic C/C++ knowledge and a Visual Studio (Express) environnement.

manuell
  • 7,528
  • 5
  • 31
  • 58