簡體   English   中英

圍繞C ++方法編寫JNI包裝器

[英]Write a JNI wrapper around a C++ method

我有三個要在Android Studio中使用的C ++文件。

  • 標頭
  • A.cpp(包含主方法和其他方法)
  • 丙型肝炎

我已經將它們編譯成靜態庫。 現在,我想圍繞C ++方法編寫JNI包裝器,並將其調用到Java部分中。 到目前為止,這是我的包裝器:

#include <jni.h>
#include <string.h>
#include <stdlib.h>

extern "C" {


   JNIEXPORT int JNICALL Java_cgi_pi_detect(? ,?) {

   IplImage * byteQueryImage = loadByteImage ( ? );
  if ( !byteQueryImage )
  {
    printf ( "couldn't load query image\n" );
    return -1;
  }

  // Detect text in the image
  IplImage * output = textDetection ( byteQueryImage, atoi(1));
  cvReleaseImage ( &byteQueryImage );
  cvSaveImage ( ? , output );
  cvReleaseImage ( &output );
  return 0;
}
}

我想給它兩張圖片作為參數:一張加載IplImage * byteQueryImage = loadByteImage ( ? ); 還有一個保存cvSaveImage ( ? , output ); 這兩個參數的jni類型JNIEXPORT int JNICALL Java_cgi_pi_detect(? ,?)應該是什么(如果我認為圖片是.png)?

您可以將包裝器函數放在將被編譯的文件中,無論是新文件還是現有文件。 與Java不同,在C ++中,文件名對編譯器沒有意義。

如果您不想獨立於Java調用其他方法,則無需包裝其他方法。

PS:請注意,包裝器函數的名稱Java_cgi_pi_detect是從定義此detect本機方法的Java類派生的。 使用javah工具生成實現本機Java方法的C函數的正確名稱。

像這樣調用main()充滿了危險。 哪個 main()將被調用? JVM可執行文件還具有main() (是的,我忽略了“未定義的行為”,因為問題在於如何使其工作。)

獲取所需main()的困難方法是將其編譯為共享對象,加載該共享對象,然后使用dlopen()dlsym()通過運行時動態鏈接自己在該共享對象中找到main() dlsym() (錯誤檢查省略):

#include <dlfcn.h>
...
// use a typedef for the function pointer
typedef int ( *main_func_t )( int, char ** );
...
// Handle to your .so with your "main()" in it
// make them static so they're only loaded once
static void *libHandle = NULL;
static main_func_t libMain = NULL;

if ( NULL == libHandle )
{
    libHandle = dlopen( "yourLibName.so", RTLD_NOW );
    libMain = ( main_func_t ) dlsym( libHandle, "main" );
}
...

// now call the main() in that library
int mainRetVal = libMain( argc, argv );
...

因此,這意味着您需要兩個共享對象:第一個“普通”對象包含您的JNI調用,第二個包含您要調用的“ main()”。 需要使用-ldl鏈接器參數將第一個“常規” JNI庫與對libdl.so的依賴libdl.so進行鏈接。

簡單的方法?

將要調用的main()重命名為其他名稱,並將其放入普通的JNI共享對象中。 然后只需調用它-它不再稱為main()因此不再存在任何名稱沖突。

即使有所有這些,我懷疑您仍然可能會遇到問題-名稱沖突或不兼容的庫會立即浮現在腦海。

一個更簡單的方法起作用嗎?

在子進程中運行它是因為它被設計為可以運行的方式,並且無論如何實際上都是一個黑匣子:您使用參數對其進行調用,它會做任何事情,並且會返回一個int返回值。 對於函數調用或子過程來說都是一樣的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM