Recently in c Category
java 调用dll文件时
几个注意点:
1. package的使用
2. javah的使用
3.path路径的设定
下面实例介绍java调用dll中的Max函数:
hello.java
package 2hei.net.dll;
public class hello
{
static
{
//System.out.println(System.getProperties().get("java.library.path"));
System.loadLibrary("Hello");
}
public native static int Max(int a,int b);
public static void main(String[] args)
{
int maxnum = 0;
int aa = 10;
int bb = 11;
hello hi= new hello();
maxnum = hi.Max(aa,bb);
System.out.println("max is "+maxnum);
}
}
生成.h头文件
createh.bat
cd E:\src\java\2hei\net\dll
javah hello
会生成一个2hei_net_dll_hello.h的文件
编辑编辑 2hei_net_dll_hello.h 把#include <jni.h> 改成#include "jni.h"
从jdk的目录里面找到jni.h 和 jni_md.h
下面使用VC++生成dll文件。
新建一个dll工程,比如Hello 编辑Hello.cpp
// Hello.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "Hello.h"
#include "2hei_net_dll_hello.h"
JNIEXPORT jint JNICALL 2hei_net_dll_hello_Max
(JNIEnv *, jclass, jint a, jint b)
{
if(a>=b)return a;
else
return b;
}
编译工程后,在Debug目录中找到Hello.dll文件,放到java的path目录下面。
执行hello.java 即可以得到想要的结果。
构造函数的作用是给每个对象的数据成员合适的初始值。构造函数的名字与类的名字相同,没有返回值。一个类可以有多个构造函数,通过不同的形参表进行区分。
创建一个类的对象时,编译器自动调用构造函数。
构造函数不能声明为const。当创建的类的对象为const时,调用普通的构造函数即可。const Item A = Item();
构造函数可以包含一个初始化列表。初始化列表以 “:”开始,以“,”分隔数据成员,每个数据成员后面是放在括号里的初始化式。(初始化式只在构造函数的定义中,不在声明中出现。)
Sales_item::sales_item(const string book):isbn(book),units_sold()0 {}
类通过默认构造函数初始化没有被显示初始化的成员变量。没有默认构造函数的类类型以及const或饮用类型的成员必须在构造函数初始化列表中进行初始化。
构造函数初始化列表仅指定用于初始化成员的值,并不指定初始化的顺序。成员被初始化的顺序就是声明成员的顺序。建议按照成员声明的顺序编写初始化列表。
如果类包含内置或复合类型(如指针、数组),应该定义自己的构造函数来初始化这些成员。
当构造函数声明为explicit时,可以防止在需要隐式转换的上下文中使用构造函数。
每个派生类构造函数除了初始化自己的数据成员以外,还要初始化基类成员,但是只能初始化直接基类的成员。直接基类就是在派生类列表中指定的类。
派生类执行构造函数时,先执行基类的构造函数,然后初始化派生类中的成员。
基类可以被包含在派生类的初始化列表中,从而被初始化。
析构函数用以完成资源释放。
只有删除指向动态分配对象的指针或实际对象(不是对象引用)超出作用域时,才会运行析构函数。
编译器总会合成一个析构函数。合成的析构函数按照对象创建时的逆序撤销每个非static成员。不删除指针成员所指的对象。
析构函数没有返回值,没有形参。
虚函数实现C++中的多态(polymorphism)。只有指定为虚函数的成员才能进行动态绑定。必须通过基类的引用或指针对虚函数进行调用。
通过引用或指针调用虚函数时,编译器将生成代码,运行时确定调用哪个函数。被调用的函数时与动态类型相对应的。
虚函数编译处理的方式:
VTABLE机制。编译器发现一个类中有虚函数时,会为其创建一个虚函数表,即VTABLE。VTABLE实际上是一个函数指针的数组,每个函数占用这个数组的一个slot。一个类只有一个VTABLE。派生类有自己的VTABLE,与基类有相同的函数排列顺序。创建类实例,调用构造函数时,编译器会在每个实例的内存区中增加一个VPTR字段,该字段指向VTABLE。
虚函数的语法:virtual function();
基类中声明的虚函数在派生类中也是虚函数。
基类的析构函数必须是虚函数。
class A
{
~A();
}
class B
{
~B();
}
void foo
{
A *a = new B;
delete a;
}
上面的例子,delete a时,只有A::~A()被调用,B::~B()没有被调用。将A的析构函数改为virtual ~A(),上面例子中的B::~B()才被调用。
基类private 的虚函数,派生类可以访问。
一个类的虚函数在它自己的构造函数和虚函数中调用时,就变成普通函数了。
纯虚函数: virtual function() = 0;
一个函数声明为纯虚函数后,其所在的类为抽象类,不能被实例化。
一直对C++中的引用没有太深刻的认识,这几天趁着工作不忙,认真地学一习了一番,在这里总结一下。
引用(reference):某一变量的别名,对引用的操作与对对象的操作一样。
引用的声明方法: 类型标示符 &引用名 = 目标变量名
声明引用时,必须同时对其进行初始化。
一旦引用被初始化指向一个对象,不能改变为另一个对象的引用。(这一点是与指针的最大区别)
引用不能为NULL。
引用最大的作用是用作函数的参数。当引用被函数改变时,相应的变量被改变。如果传递的数据块比较大,使用引用或指针,可以避免将整块数据全部压栈。
常引用
const 类型标示符 & 引用名 = 目标变量名
不能通过引用,修改目标变量值。引用型参数应该在能被定义为const的情况下尽量定义为const。
今天看了一篇文章,才知道自己对delete和free的理解不对。
从前以为指针使用delete或free释放之后就万事大吉了,但事实上用delete和free释放指针内存后,指针并不会被置为空。如果在后面的程序通过判断指针是否为空来进行不同的操作,很可能导致错误,所以,今后在用delete和free释放指针内存后,一定要把指针置为空。
既然谈到了delete和free,就要说说new/delete和malloc/free。
delete和free是C++的运算符,malloc和free是C++/C语言的标准库函数,它们都是用来动态的申请和释放内存。new和delete用于对象的申请和释放。new可以完成动态内存分配和初始化工作(构造过程),delete完成清理与释放内存的工作(析构过程)。malloc和free用于类内部数据类型(无需构造和析构)内存的申请和释放。
用new创建数组,只能用对象的无参数构造函数:
Obj *objects = new Obj[100];
在用delete释放对象数组是,不要丢了[]:
delete []objects;
如果用delete objects;相当于delete objects[0],漏掉了另外99个对象。




