0

私はJavaネイティブインターフェースを使用するのが初めてです。私の仕事は、vc++ メソッドを実装することです。

ジャバ。Javaで実装する必要があるメソッドは、vc ++内のdllメソッドを使用します

方法。私の質問は、Java でネイティブ メソッドを宣言し、

ネイティブに宣言されたメソッド、またはコードを C++ から Java に書き直す必要がありますか?

jni。誰かがこれを行う方法について私に提案できますか、私は記事を読みましたが、完全ではありませんでした

jniが何をしているかを理解してください。これは、Java で実装する必要があるメソッドです。

内部的に呼び出されるメソッドは m_hSecdll からのものなので、これらのメソッドをどのように使用すればよいですか?

この getauthorization メソッドを実装する Java

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

1 に答える 1

0

JNI

JNI では、C または C++ で Java メソッド (クラスの静的メンバーまたはオブジェクト インスタンス メンバー) を実装します。C または C++ コードは、JNI 関数を使用してパラメーターを Java からネイティブに転送し、ネイティブ関数を呼び出してから、JNI 関数を使用して戻り値をネイティブから Java に転送します。もちろん、両方の型システムで同じ表現を持つ単純な型は、変換する必要はありません。また、JNI 関数を使用して、Java オブジェクトの作成、メソッドの呼び出し、フィールドへのアクセス、例外のスローと処理を行うこともできます。

重要な参考資料:

JNA

JNA では、Java で DLL 関数を呼び出します。JNA は内部で JNI を使用しますが、C または C++ を自分で記述する代わりに、Java コードを記述して、JNA ライブラリが DLL 関数を呼び出し、パラメーターを変換して値を返す方法を記述します。

JNAを理解するのに役立つクールなツール:

  • JNAerator (必要な DLL 関数および構造の単純化された C ヘッダーと共に使用)

GetAuthorizationHeader

これは C++ クラスのメンバーのようです。それが静的ではなく、Java ネイティブ メソッド呼び出し間でそのインスタンスへの参照を保持する必要がある場合、問題ははるかに大きくなります。静的である (または静的にできる) 場合は、JNI ルートを使用すれば直接使用できます。ただし、GetAuthorizationHeader の実際の機能は非常に単純に見えるため、インラインで再実装するか、JNA ルートを使用して Java で再実装できます。

ストリングス

すべての文字列には、文字セットとエンコーディング (別名コード ページ) があります。Java は Unicode UTF-16LE または UTF-16BE (プラットフォームに依存) を使用します。Windows は UTF-16LE を使用します。コードは両手利きの _T() マクロを使用して記述されており、両利きの Win32 API 関数を呼び出します。Win32 には FunctionA 関数と FunctionW 関数があります。W はユニコードです。ほとんどの場合、Unicode をサポートしていないバージョンのWindowsのサポートを中止できます。最新の Windows で A 関数を呼び出す場合は、Unicode に変換して元に戻す必要があるため、とにかく W 関数を呼び出すこともできます。

Visual C++ の文字列リテラルは、Unicode の L"string" として記述され、型指定されwchar_t、UTF-16LE です。C++ ではwchar_t、プラットフォームに依存する文字型です。お使いの C++ のバージョンは新しい C++ をサポートしていない可能性があるため、char16_t代わりにwchar_t.

文字列で JNI を使用する場合、 関数GetStringCharsNewString関数を呼び出して、Win32 API W 関数との間で UTF-16LE 文字列を取得できます。変換は必要ありません。コードユニット数やバイト数を追跡​​するようにしてください(そして、呼び出される関数に適切なものを使用してください)。C++ の STL を使用している場合は、std::wstringクラスが役立つ場合があります。

アルゴリズムに特定のエンコーディングが必要な場合は、それが何であるかを調べる必要があります。次に、Java String および Charset クラスを使用して、エンコーディングを Java バイト配列との間で変換したり、Java バイト配列をネイティブ バイト配列との間で変換したりして、DLL 関数で使用することができます。

アルゴリズムは気にしないかもしれませんが、2 つのシステムが文字列データを交換している場合は、とにかく特定のエンコーディングを使用する必要があるかもしれません。

于 2013-11-09T21:54:35.690 に答える