// callJava.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"#include <iostream>
#include <cassert> //assert需要  #include <jni.h> //jdk 的头文件  using namespace std;  struct JVMInfo
{  JavaVM* jvm;  JNIEnv* env;  JavaVMInitArgs vm_args;  #define VM_OPT_COUNT 3  JavaVMOption options[VM_OPT_COUNT];  JVMInfo()  : jvm(0), env(0)  {  options[0].optionString = const_cast<char *>("-Djava.compiler=NONE");  //classpath有多个时,用";"分隔,UNIX下以":"分割。    options[1].optionString = const_cast<char *>("-Djava.class.path=.;C:\\Program Files\\Java\\jdk1.6.0_31\\lib\\dt.jar;C:\\Program Files\\Java\\jdk1.6.0_31\\lib\\tools.jar"); //这里,至少要包含前面java代码编译出来的Greeting.class文件所在路径  //根据我设置的相对路径,可以推出我的callJava 的C++工程和demo的Java工程所在位置的相对关系。  //用于跟踪运行时的信息    options[2].optionString = const_cast<char *>("-verbose:none"); //"-verbose:jni" 换成这个,则jvm启动时,不会在屏幕上输出一堆信息  //JNI版本号  vm_args.version = JNI_VERSION_1_6;    vm_args.nOptions = VM_OPT_COUNT;    vm_args.options = options;    vm_args.ignoreUnrecognized = JNI_TRUE;                    }  //创建VM  bool Create()  {  assert(NULL == jvm && NULL == env);  //初始化虚拟机    return 0 == JNI_CreateJavaVM(&jvm, (void**)(&env), &vm_args);    }  //释放掉VM  void Destroy()  {  if (jvm)  {  jvm->DestroyJavaVM();  jvm = 0;  env = 0;  }  }  //一个演示功能  void Demo()  {  assert(NULL != jvm);  do  {  jclass cls = env->FindClass("Greeting");  #define BREAK_ON_FAIL(fail_condition, fail_msg)  if (fail_condition){ cerr << fail_msg << endl; break; }   BREAK_ON_FAIL(!cls, "Can't found class 'Greeting'!");  //找Greeting类的构造函数  jmethodID ctor = env->GetMethodID(cls, "<init>", "()V");  BREAK_ON_FAIL(!ctor, "Can't found class' ctor !");  //构建一个Greeting的对象  jobject obj = env->NewObject(cls, ctor);  BREAK_ON_FAIL(!obj, "Can't create a object of 'Greeting'!");  //找SayHello函数  jmethodID midOfSayHello = env->GetMethodID(cls, "SayHello", "()V");  BREAK_ON_FAIL(!midOfSayHello, "Can't found class' method 'SayHello()'!");  //调用obj 的 SayHello 函数  env->CallObjectMethod(obj, midOfSayHello);  }while(false);  }
};  int main()
{          JVMInfo jvmInfo;  if (!jvmInfo.Create())  {  cerr << "Create JVM fail!" << endl;  return -1;  }  cout << "C++++++++++" << endl;  jvmInfo.Demo();  jvmInfo.Destroy();  cout << "C++++++++++" << endl;   return 0;
}
/*
int _tmain(int argc, _TCHAR* argv[])
{return 0;
}
*/
public class Greeting {  public void SayHello() {  System.out.print("--------Hello C++, I'm Java.----------\n");  }  public static void main(String[] args){new Greeting().SayHello();}}

罗裳轻解,看C++怎样拥java入怀……

分类: 白话C++ 辅助课程2011-08-06 16:06 1241人阅读 评论(11) 收藏 举报
javac++jvmpython语言jdk

前言

在公司里维护一个网络后台服务端程序,用C++写的,为了一些灵活性,就想集成个脚本语言,因为lua似乎没有什么库(或者是我对它比较无知),于是就选了老牌的python。确实噢,这家伙基本什么c/c++的库,都有它的封装。于是在服务端程序里,嵌了一个python的解释器。

可惜事情没有这么美好,公司里会python本来就不多,并且多数仅在入门。

让学Java的人去学习python? 有木有发现一个现象:学java的程序员们相对都比较自我封闭,基本都不爱再学门语言什么的,爱稳定,不爱折腾(凡客体?)

好吧,我知道java不是脚本语言,但反正它编译成class之后,也是交给c/c++的程序去执行的,这么一讲,它和php,python也差不多,可以当成需要伪编译一下脚本语言来看了——呀,我知道python也可以交给net平台或jvm上运行的,s可是这两个家伙不是C写的程序吗? (最近我写一句话:世界上只有两种语言,第一种是C语言,第二种是由C语言写成的语言,包括C语言)。

一、要做成什么效果?

1.1 表面作用就这样——

先让java程序员,在Eclipse或什么IDE里,写一段java代码。比如输出一句 hello world。然后编译成一个class文件。

然后在运行我们写的C++程序,这个程序就执行那一段java代码,于是在屏幕上输出一句hello world。

1.2 应用到工作中?

将些功能,交给Java程序员实现,然后通过这套机制,实现一个由C++写的,已经编译好的程序,可以将后面业务上需要的一些新功能或变化功能,交给Java实现。这个有实际意义至少: a因为现在的一般公司组成,确实C++程序员比较少。b另外C++要把事情做好,确实比它要把事情做糟的门槛,要高得多。c最后,相比java这样有很多高阶特征的语言,c++这样太静态的语言所缺乏一些动态性,有时挺烦人的,比如就没法通过wsdl来动态生成一个ws的调用代码(因为没有反射功能)。

二、准备工作

1.1 C++方面

还是我们常用的 Code::Blocks,也还是 gcc;别的好像也没有了,当然,用微软的VC也可以用,只是一些设置的界面不一样。

1.2 Java方面

一是要装JDK

JDK和其它c,c++文件也没有什么两样,里面有提供给C,C++的源文件,有include目录,有lib目录好像。

我装在E盘,路径是:

E:\Program Files\Java\jdk1.6.0_26 。所以你也就知道了我装的jdk是什么版本的。

那些完全没玩过java的同学注意,可能你的windows里已经有装过jvm,比如安装oracle时,不过jvm只是java虚拟机,JDK才是你要在jvm上开发的SDK。因为JVM是c写的,所以它的SDK里的东东,基本就是C和C++的头文件、以及c编译出来的库文件。

二是装了一个Eclipse

当然,用不用或用什么IDE都没关系。

三是写一段java代码:

[java] view plaincopy
  1. public class Greeting {
  2. public void SayHello() {
  3. System.out.print("--------Hello C++, I'm Java.----------\n");
  4. }
  5. }

这样小的一段代码,强大的Eclipse在我存盘时,就把它编译好了。于是我立即在Java工程目录的bin子目录下,找到了 Greeting.class文件。

我没有写java的main函数及类,反正那只是约定好的入口,我们也不需要。我们准备让自己写的c++程序来决定要从java的哪个类的哪个方法执行起——说得好像很有得选择似的,其实本例中,只有一个类,叫Greeting,一个方法,叫SayHello。不是静态方法,所以调用之前,我们要在c++代码里,先创建一个对象,这是后话。

三、C++项目配置

1.1 创建C++项目

步骤一:用code::blocks的向导,生成一个空的 c++ 控制台(console)项目,项目名称命名为 callJava。

1.2 配置JDK头文件与库文件的搜索路径

步骤二:因为要用到jdk的头文件和库文件,我们又不想把它们都给复制一份到我们callJava的项目目录下,所以需要设置一下路径。

这个方法有很多,最简单的是直接写绝对路径,但我不喜欢这个工程换台器就编译不了。另外我也不想这样一个临时试验性的工作,专门为java的库在c::b里设置一个全局路径变量。所以我们单独为这个项目(calljava)设置一个变量好了。

打开项目的“build options/构建条件”对话框,然后:

然后,就用这个变量名,在项目配置里,加上 jdk 头文件的包含路径:

最后是 库文件的链接路径,操作类似,只是换了一页:

1.3为项目添加链接库

以上配置,等于是让编译器知道上哪些个文件夹里,去找它所需要 jdk的头文件和库文件,不过最重要的是,它需要的是文件?头文件当然是在代码里写上,库文件呢,我们还需要配置一下。这个例子很简单,我们只需要一个叫 jvm.lib的文件:

这个文件,你可以在一开始说的那个jdk安装子目录lib下找到。

四、C++ 代码

终于到写C++代码了。就直接在向导自动生成的main.cpp里写吧。

[cpp] view plaincopy
  1. #include <iostream>
  2. #include <cassert> //assert需要
  3. #include <jni.h> //jdk 的头文件
  4. using namespace std;
  5. struct JVMInfo
  6. {
  7. JavaVM* jvm;
  8. JNIEnv* env;
  9. JavaVMInitArgs vm_args;
  10. #define VM_OPT_COUNT 3
  11. JavaVMOption options[VM_OPT_COUNT];
  12. JVMInfo()
  13. : jvm(0), env(0)
  14. {
  15. options[0].optionString = const_cast<char *>("-Djava.compiler=NONE");
  16. //classpath有多个时,用";"分隔,UNIX下以":"分割。
  17. options[1].optionString = const_cast<char *>("-Djava.class.path=./demo/bin"); //这里,至少要包含前面java代码编译出来的Greeting.class文件所在路径
  18. //根据我设置的相对路径,可以推出我的callJava 的C++工程和demo的Java工程所在位置的相对关系。
  19. //用于跟踪运行时的信息
  20. options[2].optionString = const_cast<char *>("-verbose:none"); //"-verbose:jni" 换成这个,则jvm启动时,不会在屏幕上输出一堆信息
  21. //JNI版本号
  22. vm_args.version = JNI_VERSION_1_6;
  23. vm_args.nOptions = VM_OPT_COUNT;
  24. vm_args.options = options;
  25. vm_args.ignoreUnrecognized = JNI_TRUE;
  26. }
  27. //创建VM
  28. bool Create()
  29. {
  30. assert(NULL == jvm && NULL == env);
  31. //初始化虚拟机
  32. return 0 == JNI_CreateJavaVM(&jvm, (void**)(&env), &vm_args);
  33. }
  34. //释放掉VM
  35. void Destroy()
  36. {
  37. if (jvm)
  38. {
  39. jvm->DestroyJavaVM();
  40. jvm = 0;
  41. env = 0;
  42. }
  43. }
  44. //一个演示功能
  45. void Demo()
  46. {
  47. assert(NULL != jvm);
  48. do
  49. {
  50. jclass cls = env->FindClass("Greeting");
  51. #define BREAK_ON_FAIL(fail_condition, fail_msg)  if (fail_condition)  \
  52. { cerr << fail_msg << endl; break; }
  53. BREAK_ON_FAIL(!cls, "Can't found class 'Greeting'!");
  54. //找Greeting类的构造函数
  55. jmethodID ctor = env->GetMethodID(cls, "<init>", "()V");
  56. BREAK_ON_FAIL(!ctor, "Can't found class' ctor !");
  57. //构建一个Greeting的对象
  58. jobject obj = env->NewObject(cls, ctor);
  59. BREAK_ON_FAIL(!obj, "Can't create a object of 'Greeting'!");
  60. //找SayHello函数
  61. jmethodID midOfSayHello = env->GetMethodID(cls, "SayHello", "()V");
  62. BREAK_ON_FAIL(!midOfSayHello, "Can't found class' method 'SayHello()'!");
  63. //调用obj 的 SayHello 函数
  64. env->CallObjectMethod(obj, midOfSayHello);
  65. }while(false);
  66. }
  67. };
  68. int main()
  69. {
  70. JVMInfo jvmInfo;
  71. if (!jvmInfo.Create())
  72. {
  73. cerr << "Create JVM fail!" << endl;
  74. return -1;
  75. }
  76. cout << "C++++++++++" << endl;
  77. jvmInfo.Demo();
  78. jvmInfo.Destroy();
  79. cout << "C++++++++++" << endl;
  80. return 0;
  81. }

解释就看注释吧,或者在网上搜索一下同类文件。

四、运行效果

C++代码编译通过,按F9运行……

这只是一个试验用的例子,根据在当初拥Python入怀的经验教训下,知道要用这种方法来运行大的,包括多线程的java的代码,还要调用JDK中和并发有关的许多事。

三行输出都来自同一个程序,只是其中上下两行 C++++++++++++++++是来自C++的代码,中间一句来自Java代码。现在,我们不再管C++程序,邀请一位Java程序员,让他帮助改改那段 Greet的SayHello函数,就可以直接从运行效果中体现出来修改效果。

罗裳轻解,看C++怎样拥java入怀……相关推荐

  1. 《野兽绅士》总结5——用联系与约会拥她入怀

    本系列来源于笔者阅读<野兽绅士>后的总结,希望各位帮助各位单身男性找到适合自己的另一半. 目录 越古老的开始越经典 短信息是打开互动的钥匙 短信息互动八法则 通话的第一句犹如神谕 第一通电 ...

  2. 猫书 如何轻松拥猫入怀

    ISBN:978-7-5596-3523-5 作者:[日]今泉忠明 插图:中西直子 译者:付越 页数:245页 阅读时间:2021-08-08 推荐指数:★★★★★ 里面讲了猫咪的思维和习性, 如何与 ...

  3. java书籍_Java程序员必看的 13 本 Java 书籍!

    原文:Java程序员必看的 13 本 Java 书籍! 作者: java技术栈 关乎于程序员,除了做项目来提高自身的技术,还有一种提升自己的专业技能就是:多!看!书! 毕竟,书是学习的海洋呢!So,J ...

  4. java和python的web自动化有什么区别-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  5. python和java一样吗-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  6. 代理后台中间件_Golang Gin 实战(十三)| 中间件详解看这一篇就够了

    6000字大章带你死磕Golang Gin中间件 在Gin的整个实现中,中间件可谓是Gin的精髓.一个个中间件组成一条中间件链,对HTTP Request请求进行拦截处理,实现了代码的解耦和分离,并且 ...

  7. python和java的区别-三分钟看懂Python和Java的区别

    随着人工智能的火爆,Python和Java一直在各种流行编程语言中名列前茅.其实Java和Python有些相似,因为很多编程语言之间是互通的.Java现在还是第一,不知道Python未来会不会超越Ja ...

  8. JAVA 入坑教程 | 章节九 详解java的装箱和拆箱

    简单点,代码的方式简单点,装逼的方式请省略,我们又不是演员,别设计那些情节 什么是装箱?什么是拆箱?代码如何展示? 装箱过程是怎样的?拆箱过程是怎样的? 有问题可加入安卓QQ群: 246231638 ...

  9. 第九回(一):任侠厨子轻解厄围 夜半蹴鞠为泄忿闷

    (一)第九回:任侠厨子轻解厄围   夜半蹴鞠为泄忿闷 诗曰:                  阶上回首十年馀,后山契语归何处? 忍忆泼悍遮旧容,几度含凄整鱼书. 却说阿四二人方出阿清店门,便有三名身 ...

最新文章

  1. 001/Docker入门(Mooc)
  2. linux 抓包 tcpdump和Wireshark
  3. NKU两题简单题解析(递归分析与位运算技巧)
  4. c++服务器开源项目,开源一个c++ lua服务器框架
  5. python测试代码性能_使用python timeit 模块检测代码性能
  6. 使用BaseAdapter实现复杂的ListView
  7. 21天让你成为Horizon View高手—Day18:Windows操作系统优化
  8. 自定义ListView中的分割线
  9. eclipse error
  10. 1,3-丁二烯(BD)行业调研报告 - 市场现状分析与发展前景预测
  11. 中文命名实体识别,HMM,CRF,BiLSTM,BiLSTM+CRF的具体实现
  12. 洛谷——P1614 爱与愁的心痛
  13. 目前主流的数据库有哪些?
  14. windows7经典开机音乐_那些经典的单机游戏背景音乐,带你找寻童年记忆
  15. 相机标定matlab版本,相机标定 matlab
  16. 使用backdrop-filter部分场景的替代效果
  17. BUU Web[33-36]
  18. 图片点击放大,你的网页也能做到!
  19. 火云开发课堂 - 《Shader从入门到精通》系列 第九节:在Shader中实现马赛克滤镜
  20. node.js的第三方模块 nodemon、nrm、Gulp、Gulp插件

热门文章

  1. 在线代理浏览国外网站_知道这些在线PS网站,设计再也不求人
  2. 【写博客常用】sql server 登陆服务器名称是什么
  3. 51单片机入门学习 第八天
  4. 《活出最乐观的自己》
  5. 衡水中学2021年的高考成绩查询,2021年“百强高中”排名公布,第一名一本率99.5%,衡中进前三...
  6. 使用VPB生成OSG的.ive格式地形方法
  7. vpb输出范围地形命令
  8. 不能共情你还当什么领导
  9. SpringSession实战项目(基于SpringBoot项目)【附源码】
  10. 【机器学习】图像语义分割常用指标Dice系数 敏感性 特异性 IOU及python代码实现