存档

‘C/C++’ 分类的存档

对linux和windows的动态库总结

2009年9月26日

windows下:

根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。

(1)静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码(Windows系统负责对DLL调用次数的计数),调用方式简单,能够满足通常的要求。通常采用的调用方式是把产生动态连接库时产生的.LIB文件加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。 LIB文件包含了每一个DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码(这里的lib文件和静态库是不一样的)。Lib文件包含的信息进入到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。

(2)动态调用,即显式调用方式,是由编程者用API函数加载和卸载DLL来达到调用DLL的目的(比如LoadLibrary、GetProcAddress、FreeLibrary),比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。

静态调用举例:

首先编制一个DLL,简单由2个文件组成:ShowInfo.h ShowInfo.c 代码如下:

ShowInfo.h:

  1. #ifdef SHOWINFO_EXPORTS
  2. #define SHOWINFO_API __declspec(dllexport)
  3. #else
  4. #define SHOWINFO_API __declspec(dllimport)
  5. #endif
  6. SHOWINFO_API void fnShowInfo(void);

ShowInfo.c:

  1. #include "ShowInfo.h"
  2. #include <stdio.h>
  3.  
  4. SHOWINFO_API void fnShowInfo(void)
  5. {
  6. printf("Crab\n");
  7. }

编译时,务必打开SHOWINFO_EXPORTS宏开关,这样DLL里面的函数申明就会带有__declspec(dllexport)关键字了(否则生成不了lib文件),构建完后,就生成了一个lib文件,一个dll文件

使用这个DLL的时候,需要做如下事情,第一:导入ShowInfo.h,但不要打开SHOWINFO_EXPORTS宏开关,这样函数声明就变成了__declspec(dllimport);第二:编译时导入刚才生成的lib包;第三:将dll放在exe的所在目录,或者VC的工程目录。

上面这个制作DLL和使用DLL的方式,其实就是JNI的方式,可以拿javah生成的对比下。

还有一种方式是用(.DEF)模块定义文件,个人暂不倾向这个,呵呵。

linux下:

linux环境要干净透明些,无需在函数名上挂狗牌。如果要制作动态库,写好C文件后,直接用 gcc ShowInfo.c -fPIC -shared -o libShowInfo.so 就搞定了。也就是加个-fPIC -shared 参数,指定GCC不要链接成可执行文件,而是动态库。这里要注意几点:一、libShowInfo.so的命名方式,一定要 lib*.so这样的命名;二、-shared是指编译成动态库,-fPIC学问稍微大些,如果不指定它,那么其他程序调用这个so的时候,它会为每个程序维护一个副本,其实,对于小型的dll,完全没有必要指定-fPIC,效率会非常高的,但是对于大型的dll,那么还是指定下吧。使用就更简单了,gcc Main.c -L. -lShowInfo -o Main,其中-L指明让GCC去哪里找动态库,-l则是指定动态库的名字(lib*.so中间的*就是名字),顺提一句,如要要使用数学类的方法,得加上 -lm,是指用一个数学动态库。

上面讲的,其实就是类似于windows的静态调用,在linux下,同样也是可以用动态方式加载和使用dll了,这里就不讲了。另外,在Linux里面,可以采用ldd命令来检查程序所依赖的共享库。

C/C++ , , , ,

CUnit的精简测试框架

2009年7月24日

CUnit使用起来需要去写一些和CUnit相关的代码才能跑起来,没有JUnit4.0那种POJO的方式来的这么清爽,于是我定义了一些宏,将和业务无关的CUnit代码屏蔽起来,使用的时候,针对每个.C文件写一个测试suit文件,让它们一起包含Test.h即可。

200907241927

Test.h出了包含一些头文件以外,还有一串宏,定义如下(下面的中文是举例):

  1. #include "include/Basic.h"
  2.  
  3. #define INITIALIZE_CUNIT() \
  4.  if (CUE_SUCCESS != CU_initialize_registry()) \
  5.   return CU_get_error();
  6.  
  7. #define FINISH_CUNIT() \
  8.  CU_basic_set_mode(CU_BRM_VERBOSE); \
  9.  CU_basic_run_tests(); \
  10.  CU_cleanup_registry(); \
  11.  return CU_get_error();
  12.  
  13. #define NewTestSuit(SuitName) \
  14.  CU_pSuite pSuite = NULL; \
  15.  pSuite = CU_add_suite("Suite_Of_"#SuitName, before, after);
  16.  
  17. #define AddTest(FunctionName) CU_add_test(pSuite, #FunctionName, FunctionName);
  18.  
  19. #define GoTests() \
  20.  test模块1(); \
  21.  test模块2(); \
  22.  test模块3();
  23.  
  24. void test模块1(void);
  25. void test模块2(void);
  26. void test模块3(void);

下面是TestMain.c,以后可以不用动。

  1. #include "Test.h"
  2. int main(){
  3.  INITIALIZE_CUNIT();
  4.  GoTests();
  5.  FINISH_CUNIT();
  6. }

下面给出 Test模块1.c 的例子

  1. #include "Test.h"
  2. static int before(void){
  3.  // 该模块的方法运行前的准备工作写在这里
  4.  return 0;
  5. }
  6. static int after(void){
  7.  // 运行完的销毁工作也在这里
  8.  return 0;
  9. }
  10. void test_方法1(void)
  11. {
  12.  CU_ASSERT_EQUAL(1, 1);
  13. }
  14. void test_方法2(void)
  15. {
  16.  CU_ASSERT_EQUAL(1, 1);
  17. }
  18. void test_方法3(void)
  19. {
  20.  CU_ASSERT_EQUAL(1, 1);
  21. }
  22.  
  23. void test模块1()
  24. {
  25.  NewTestSuit(模块1);
  26.  AddTest(test_方法1);
  27.  AddTest(test_方法2);
  28.  AddTest(test_方法3);
  29. }

需要注意的是,和JUnit4.0有点不同:
JUnit4.0运行流程为:before->方法1->after->before->方法2->after->before->方法3->after
CUnit的运行流程为: before->方法1->方法2->方法3->after

C/C++

VC++的一些路径信息

2009年4月11日

executatble files:
C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin
C:\Program Files\Microsoft Visual Studio\VC98\BIN
C:\Program Files\Microsoft Visual Studio\Common\TOOLS
C:\Program Files\Microsoft Visual Studio\Common\TOOLS\WINNT

include files:
C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE

library files:
C:\Program Files\Microsoft Visual Studio\VC98\LIB
C:\Program Files\Microsoft Visual Studio\VC98\MFC\LIB

source files:
C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC
C:\Program Files\Microsoft Visual Studio\VC98\MFC\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE
C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC

添加时要精确点,确保这些目录都找的到,而且后面不能有空格…

C/C++ ,