Question

I'm new in using java native interface. My task is to implement a vc++ method in

java. The method which i need to implement in java uses dll methods inside the vc++

method. My question is, is it enough to declare the native methods in java and call the

native declared methods or do i still need to rewrite the code from c++ to java using

jni. Could anyone suggest me on how to do this, i read articles but didn't fully

understand what jni is doing. This is the method i have to implement in java, the

internally called methods are from the m_hSecdll, so how should i use those methods in

java to implement this getauthorization method

bool HtmlWindow::GetAuthorizationHeader(CString &sName, CString &sValue)
        {          
                //type enum
            SecStatus stat;
                //typedef for long typw
            SecContextHandle hCurrentCtx;
            //typedef for struct
                SecBufferHandle hBuf = NULL; 

            try
            {
                if (!m_hSecdll)
                {
                    m_hSecRtl = AfxLoadLibrary(_T("secdll"));
                }

                if (!m_hSecdll)
                {
                    AfxMessageBox(IDS_ERR_SECDLL);
                    return false;
                }

                //get the function to call SecGetContext
                typedef SecStatus (_stdcall *FN2)(SecContextHandle*);
                FN2 pFN2 = (FN2) ::GetProcAddress(m_hSecRtl, _T("SecGetContext"));
                if (!pFN2)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETCONTEXT);
                    return false;
                }

                //call it
                stat = (*pFN2)(&hCurrentCtx);
                if (stat != eSecOk) {
                    AfxMessageBox(IDS_ERR_MPAGES_SERVICE_CONTEXT);
                    return false;
                }

                //get the function to call SecExportContext
                typedef SecStatus (_stdcall *FN3)(SecBufferHandle*, const SecContextHandle, const char*, const uint);
                FN3 pFN3 = (FN3) ::GetProcAddress(m_hSecRtl, _T("SecExportContext"));
                if (!pFN3)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECEXPORTCONTEXT);
                    return false;
                }

                //call it
                stat = (*pFN3)(&hBuf, hCurrentCtx, NULL, 0);
                if (stat != eSecOk) {
                    AfxMessageBox(IDS_ERR_MPAGES_SERVICE_EXPORT);
                    return false;
                }

                //get the function to call SecExportContext
                typedef void* (_stdcall *FN4)(SecBufferHandle);
                FN4 pFN4 = (FN4) ::GetProcAddress(m_hSecRtl, _T("SecGetBufferPtr"));
                if (!pFN4)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETBUFFERPTR);
                    return false;
                }

                //call it
                unsigned char * c = (unsigned char*)(*pFN4)(hBuf);

                //get the function to call SecExportContext
                typedef long (_stdcall *FN5)(SecBufferHandle);
                FN5 pFN5 = (FN5) ::GetProcAddress(m_hSecRtl, _T("SecGetBufferLen"));
                if (!pFN5)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETBUFFERLEN);
                    return false;
                }

                //call it
                int length = (*pFN5)(hBuf);

                int x = 0;
                char * hex = new char[length*2];
                for (int i = 0; i < length; i++)
                {
                    CString sTemp;
                    sTemp.Format("%x",c[i]);
                    if (sTemp.GetLength()==1)
                        sTemp = _TCHAR('0') + sTemp;

                    hex[x++] = sTemp[0];
                    hex[x++] = sTemp[1];
                }

                sName = "Some String";
                sValue = CString(hex,length*2); 
                delete [] hex;

            }
            catch (...)
            {
                AfxMessageBox(IDS_ERR_SECDLL_UNKNOWN);
                return false;
            }

            return true;
    }
Était-ce utile?

La solution

JNI

With JNI, you implement Java methods (class static members or object instance members) in C or C++. The C or C++ code uses JNI functions to transfer parameters from Java to native, call native functions and then use JNI functions to transfer the return value from native to Java. Simple types that have identical representations in both type systems, of course, don't need any conversion. You can also create Java objects, call methods, access fields and throw and handle exceptions using the JNI functions.

Essential references:

JNA

With JNA, you call DLL functions in Java. JNA uses JNI internally, but instead of writing C or C++ yourself, you write Java code to describe how the JNA libraries should call the DLL functions and convert parameters and return values.

Cool tool to help understand JNA:

  • JNAerator (use with simplified C headers for DLL functions and structures you need)

GetAuthorizationHeader

This appears to be a member of a C++ class. If it's not static, and you need to keep a reference to an instance of it between Java native method calls, then your problem is much larger. If it is static (or can be made so), you could use it directly if you go the JNI route. However, the actual functionality of the GetAuthorizationHeader seems pretty simple so it could be reimplemented inline, or in Java with the JNA route.

Strings

Every string has a character set and encoding (aka code page). Java uses Unicode UTF-16LE or UTF-16BE (platform dependent). Windows uses UTF-16LE. Your code is written with the ambidextrous _T() macro and calls the ambidextrous Win32 API functions. Win32 has FunctionA functions and FunctionW functions. W is for Unicode. Most likely you can drop support for versions of Windows that don't support Unicode. If you call an A function on modern Windows, it has to convert to Unicode and back again so you might as well call the W function anyway.

String literals in Visual C++ are written as L"string" for Unicode and are typed wchar_t and are UTF-16LE. In C++, wchar_t is a platform dependent character type. Your version of C++ might not support the new-ish C++ char16_t so you can substitute wchar_t.

When using JNI with strings, you can call the GetStringChars and NewString functions to get UTF-16LE strings to and from the Win32 API W functions. No conversion needed; just be sure the keep track of code unit counts and/or byte counts (and use the proper one for the function being called). If you are using C++'s STL, then the std::wstring class might help.

If your algorithm needs a particular encoding then you have to find out what that is. You could then use the Java String and Charset classes to convert encodings to/from Java byte arrays and convert Java byte arrays to/from native byte arrays to use with your DLL functions.

It could be that your algorithm doesn't care but you might need to use a particular encoding anyway if two systems are exchanging string data.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top