如何通过JNI在Android中调用C文件中的主要功能? [英] How to call the main function in C file by JNI in Android?

查看:261
本文介绍了如何通过JNI在Android中调用C文件中的主要功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开发一个应用程序,我不得不使用 LIVE555 在Android 4.4.2。

LIVE555 是C源$ C ​​$ C为流媒体,我必须通过<叫它code> JNI 。

我有样订做以下图片为 LIVE555 中的.so:

我想通过JNI调用C源$ C ​​$ C

问题1

我应该使用加载的库的System.loadLibrary JAVA <以下code / code >?

 静态{
        的System.loadLibrary(什么函数库叫我应该载入?);
    }

问题2

如何调用 在功能上的 的Java 使用的 公共本地字符串为主;
主要功能是 JNI /媒体服务器/ live555MediaServer.cpp

的C源$ C ​​$ C live555MediaServer.cpp 是这样的:

 的#include&LT; BasicUsageEnvironment.hh&GT;
#包括DynamicRTSPServer.hh
#包括version.hhINT主(INT ARGC,字符** argv的){
  //通过建立我们的使用环境开始:
  *的TaskScheduler调度= BasicTaskScheduler :: createNew();
  UsageEnvironment * ENV = BasicUsageEnvironment :: createNew(*调度程序);  UserAuthenticationDatabase * authDB = NULL;
#IFDEF ACCESS_CONTROL
  //实现客户的访问控制RTSP服务器,请执行以下操作:
  authDB =新UserAuthenticationDatabase;
  authDB-&GT; addUserRecord(用户名1,密码1); //替换这些与真正的字符串
  //重复上述每个&lt;用户名&gt;中&LT;密码和GT;你希望允许
  //对服务器的访问。
#万一  //创建RTSP服务器。首先尝试使用默认端口号(554),
  //然后与备用端口号(8554):
  RTSPServer * rtspServer;
  portNumBits rtspServerPortNum = 554;
  rtspServer = DynamicRTSPServer :: createNew(* ENV,rtspServerPortNum,authDB);
  如果(rtspServer == NULL){
    rtspServerPortNum = 8554;
    rtspServer = DynamicRTSPServer :: createNew(* ENV,rtspServerPortNum,authDB);
  }
  如果(rtspServer == NULL){
    * ENV&LT;&LT; 无法创建RTSP服务器:&LT;&LT; env-&GT; getResultMsg()&所述;&下; \\ n;
    出口(1);
  }  * ENV&LT;&LT; LIVE555媒体服务器\\ n;
  * ENV&LT;&LT; \\ tversion&LT;&LT; MEDIA_SERVER_VERSION_STRING
       &LT;&LT; (LIVE555流媒体库的版本
       &LT;&LT; LIVEMEDIA_LIBRARY_VERSION_STRING&LT;&LT; )\\ n;  字符* URL preFIX = rtspServer-&GT; RTSPURL preFIX();
  * ENV&LT;&LT; 使用URL \\ n \\ t从该服​​务器播放流
       &LT;&LT;网址preFIX&LT;&LT; &LT;&名GT; \\ nwhere&LT;文件名中的一个是在当前目录中的文件present \\ n;
  * ENV&LT;&LT; 每个文件的类型,从它的名字后缀推断:\\ N的;
  * ENV&LT;&LT; \\ t \\264 \\=&gt;将H.264视频基本流文件\\ n。
  * ENV&LT;&LT; \\ t \\AAC \\=&gt;一种AAC音频(ADTS格式)文件\\ n。
  * ENV&LT;&LT; \\ t \\AC3 \\=&gt;一种AC-3音频文件\\ n。
  * ENV&LT;&LT; \\ t \\AMR \\=&gt;一种AMR音频文件\\ n;
  * ENV&LT;&LT; \\ t \\DV \\=&gt;将DV的视频文件\\ n。
  * ENV&LT;&LT; \\ t \\M4E \\=&gt;将MPEG-4视频基本流文件\\ n。
  * ENV&LT;&LT; \\ t \\MKV \\=&gt;将Matroska的音频+视频+(可选)字幕文件\\ n;
  * ENV&LT;&LT; \\ t \\MP3 \\=&gt;将MPEG-1或2音频文件\\ n。
  * ENV&LT;&LT; \\ t \\MPG \\=&gt;将MPEG-1或2节目流(音频+视频)文件\\ n。
  * ENV&LT;&LT; \\ t \\TS \\=&gt;将MPEG传送流文件\\ n。
  * ENV&LT;&LT; \\ t \\ T(A \\TSX \\索引文件 - 如果present - 提供服务器特技播放支持)\\ n;
  * ENV&LT;&LT; \\ t \\VOB \\=&gt;将VOB(MPEG-2视频与AC-3音频)文件\\ n。
  * ENV&LT;&LT; \\ t \\WAV \\=&gt;将WAV音频文件\\ n。
  * ENV&LT;&LT; \\ t \\WEBM \\=&gt;将WebM的音频(Vorbis格式)+视频(VP8)文件\\ n。
  * ENV&LT;&LT; 对于其他文档见http://www.live555.com/mediaServer/ \\ n;  //另外,尝试创建RTSP环比HTTP隧道HTTP服务器。
  //首先尝试用默认的HTTP端口(80),然后用替代HTTP
  //端口号(8000和8080)。  如果(rtspServer-&GT; setUpTunnelingOverHTTP(80)|| rtspServer-&GT; setUpTunnelingOverHTTP(8000)|| rtspServer-&GT; setUpTunnelingOverHTTP(8080)){
    * ENV&LT;&LT; (我们使用端口&LT;&LT; rtspServer-&GT; httpServerPortNum()&LT;&LT;对RTSP环比HTTP隧道,或HTTP实时流(可选索引传输流文件只)。)\\ n;
  }其他{
    * ENV&LT;&LT; (RTSP环比HTTP隧道不可用。)\\ n;
  }  env-&GT;的TaskScheduler()doEventLoop()。 //不返回  返回0; //只有prevent编译器警告
}

-------------------------------编辑------------ ------------------------

  JNI / live555.cpp:33:11:错误:'ARGC在此范围未声明
JNI / live555.cpp:33:17:错误:'argv的在此范围未声明
JNI / live555.cpp:33:21:错误:'主'不是在这个范围内声明


解决方案

 静态{
        //当你有更多的。所以文件秩序的问题。
        的System.loadLibrary(LIVE555);
    }

现在调用带参数的主要功能。创建一个JNI方法,该方法字符串数组,并简单地调用该方法。在JNI字符串数组转换为C字符串数组,和你做。

  JNIEXPORT return_type JNICALL Java_full_package_name_classname_functionname(JNIEnv的* ENV,jobject对象,Jobject字符串数组){
    //你的ARGC
    INT大小= env-&GT; GetArrayLength(字符串数组);
    焦炭** argv的=新的char * [尺寸]
    的for(int i = 0; I&LT;大小; ++ I)
    {
        的jstring字符串= env-&GT; GetObjectArrayElement(stringArrays,I);
        为const char *的CString = env-&GT; GetStringUTFChars(字符串,0);
        的argv [i] =的strdup(CString的);
        env-&GT; ReleaseStringUTFChars(字符串,myarray的);
        env-&GT; DeleteLocalRef(字符串);
    }
    //你将需要修改的主要所以它不正确清理
    主(ARGC,ARGV);
    // 清理
    的for(int i = 0; I&LT;大小; ++ I)
        免费(的argv [I]);
    删除[] argv的;
}

您应该尝试一些的Hello World应用程序获取Java&LT; ---> C ++ code在Android和其余的应该是相当明显的工作。检查Android的样本。他们有良好的JNI样品。

I am developing an application where I have to use the Live555 on Android 4.4.2 .

Live555 is a C source code for Media Streaming , and I have to call it by JNI.

I have build the .so for Live555 like the following picture:

I want to call the C source code by JNI

The question 1

Which libraries should I load by using System.loadLibrary like the following code in JAVA ?

static {
        System.loadLibrary("What libraries name should I load ?");
    }

The question 2

How to call the main function in java by using public native String main; (main function is in jni/mediaServer/live555MediaServer.cpp)

The C source code of live555MediaServer.cpp is like the following:

#include <BasicUsageEnvironment.hh>
#include "DynamicRTSPServer.hh"
#include "version.hh"

int main(int argc, char** argv) {
  // Begin by setting up our usage environment:
  TaskScheduler* scheduler = BasicTaskScheduler::createNew();
  UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);

  UserAuthenticationDatabase* authDB = NULL;
#ifdef ACCESS_CONTROL
  // To implement client access control to the RTSP server, do the following:
  authDB = new UserAuthenticationDatabase;
  authDB->addUserRecord("username1", "password1"); // replace these with real strings
  // Repeat the above with each <username>, <password> that you wish to allow
  // access to the server.
#endif

  // Create the RTSP server.  Try first with the default port number (554),
  // and then with the alternative port number (8554):
  RTSPServer* rtspServer;
  portNumBits rtspServerPortNum = 554;
  rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);
  if (rtspServer == NULL) {
    rtspServerPortNum = 8554;
    rtspServer = DynamicRTSPServer::createNew(*env, rtspServerPortNum, authDB);
  }
  if (rtspServer == NULL) {
    *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
    exit(1);
  }

  *env << "LIVE555 Media Server\n";
  *env << "\tversion " << MEDIA_SERVER_VERSION_STRING
       << " (LIVE555 Streaming Media library version "
       << LIVEMEDIA_LIBRARY_VERSION_STRING << ").\n";

  char* urlPrefix = rtspServer->rtspURLPrefix();
  *env << "Play streams from this server using the URL\n\t"
       << urlPrefix << "<filename>\nwhere <filename> is a file present in the current directory.\n";
  *env << "Each file's type is inferred from its name suffix:\n";
  *env << "\t\".264\" => a H.264 Video Elementary Stream file\n";
  *env << "\t\".aac\" => an AAC Audio (ADTS format) file\n";
  *env << "\t\".ac3\" => an AC-3 Audio file\n";
  *env << "\t\".amr\" => an AMR Audio file\n";
  *env << "\t\".dv\" => a DV Video file\n";
  *env << "\t\".m4e\" => a MPEG-4 Video Elementary Stream file\n";
  *env << "\t\".mkv\" => a Matroska audio+video+(optional)subtitles file\n";
  *env << "\t\".mp3\" => a MPEG-1 or 2 Audio file\n";
  *env << "\t\".mpg\" => a MPEG-1 or 2 Program Stream (audio+video) file\n";
  *env << "\t\".ts\" => a MPEG Transport Stream file\n";
  *env << "\t\t(a \".tsx\" index file - if present - provides server 'trick play' support)\n";
  *env << "\t\".vob\" => a VOB (MPEG-2 video with AC-3 audio) file\n";
  *env << "\t\".wav\" => a WAV Audio file\n";
  *env << "\t\".webm\" => a WebM audio(Vorbis)+video(VP8) file\n";
  *env << "See http://www.live555.com/mediaServer/ for additional documentation.\n";

  // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
  // Try first with the default HTTP port (80), and then with the alternative HTTP
  // port numbers (8000 and 8080).

  if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
    *env << "(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)\n";
  } else {
    *env << "(RTSP-over-HTTP tunneling is not available.)\n";
  }

  env->taskScheduler().doEventLoop(); // does not return

  return 0; // only to prevent compiler warning
}

-------------------------------EDIT------------------------------------

jni/live555.cpp:33:11: error: 'argc' was not declared in this scope
jni/live555.cpp:33:17: error: 'argv' was not declared in this scope
jni/live555.cpp:33:21: error: 'main' was not declared in this scope

解决方案

static {
        // order matters when you have more ".so" files.
        System.loadLibrary("live555");
    }

Now to call the main function with parameters. create a JNI method that takes an array of strings, and simply call that method. In the JNI convert the array of strings to array of C strings, and you are done.

JNIEXPORT return_type JNICALL Java_full_package_name_classname_functionname(JNIEnv *env, jobject object, Jobject stringArray){
    // your argc
    int size = env->GetArrayLength(stringArray);
    char **argv = new char*[size];
    for (int i=0; i < size; ++i) 
    {
        jstring string = env->GetObjectArrayElement(stringArrays, i);
        const char* cString = env->GetStringUTFChars(string, 0);
        argv[i] = strdup(cString);
        env->ReleaseStringUTFChars(string, myarray);
        env->DeleteLocalRef(string);
    }
    // you will need to modify main so it does properly cleanup
    main(argc, argv);
    // clean up
    for(int i = 0; i < size; ++i)
        free(argv[i]);
    delete [] argv;
}

You should try some hello world apps to get Java<--->c++ code working on android and the rest should be fairly obvious. Check the android samples. They have good JNI samples.

这篇关于如何通过JNI在Android中调用C文件中的主要功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆