免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 9360 | 回复: 9
打印 上一主题 下一主题

关于C调用C++动态库的例子 [复制链接]

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-03 02:36 |只看该作者 |倒序浏览
忙活了半天,对C++了解并不多,不过总算搞出了一个可以用的例子。
先解释一下,1.cc和2.cc是生成so的源文件,1.h是class的声明。so的名字叫1.so
3.c是调1.so中myfunc函数的C程序,因为C++编译后,符号会被按照编译器的规则修改,所以3.c包含了一个funcname.h,而这个funcname.h是由Makefile生成。
以下为源码:

1.cc

  1. #include "1.h"
  2. A::A()
  3. {
  4.         i=0;
  5. }
  6. void A::set(int ii)
  7. {
  8.         i=ii;
  9. }
  10. int A::get(void)
  11. {
  12.         return i;
  13. }
  14. void A::func(void)
  15. {
  16.         i++;
  17. }
复制代码


1.h

  1. #ifndef AAA
  2. #define AAA
  3. class A {
  4. protected:
  5.         int i;
  6. public:
  7.         A();
  8.         void set(int);
  9.         int get(void);
  10.         void func(void);
  11. };
  12. #endif
复制代码


2.cc

  1. #include "1.h"
  2. int myfunc(int i)
  3. {
  4.         A a;
  5.         a.set(i);
  6.         a.func();
  7.         return a.get();
  8. }
复制代码

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
2 [报告]
发表于 2007-11-03 02:47 |只看该作者
3.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <dlfcn.h>
  4. #include "funcname.h"
  5. int main()
  6. {
  7.         int i;
  8.         void* p;
  9.         char*error;
  10.         int (*f)(int);
  11.         char so_name[256];
  12.         getcwd(so_name,256);
  13.         strcat(so_name,"/1.so");
  14.         p=dlopen(so_name,RTLD_LAZY);
  15.         if(p==NULL) {
  16.                 fprintf(stderr,"dlopen error:%s\n",dlerror());
  17.                 exit(1);
  18.         }
  19.         f=dlsym(p,myfunc);
  20.         error=dlerror();
  21.         if(error!=NULL) {
  22.                 fprintf(stderr,"dlsym:%s\n",error);
  23.                 exit(1);
  24.         }
  25.         i=f(1);
  26.         printf("%d\n",i);
  27.         return 0;
  28. }
复制代码


Makefile

  1. CC=gcc
  2. CXX=g++
  3. CPPFLAGS=-fPIC
  4. SO_SRC=1.cc 2.cc
  5. FUNCNAME_H=funcname.h
  6. FUNC=myfunc
  7. SRC=3.c
  8. OBJ:=$(SRC:.c=.o)
  9. CFLAGS=
  10. SO=1.so
  11. EXC=a.out

  12. .PHONY : all  clean
  13. all:$(SO) $(EXC)

  14. $(SO):$(SO_SRC:.cc=.o)
  15.         $(CXX) -shared -Wl,-soname,$(SO) -o $(SO) $^

  16. $(EXC):$(FUNCNAME_H) $(OBJ)
  17.         $(CC) $(OBJ) -ldl -o $(EXC)

  18. $(FUNCNAME_H):$(SO)
  19.         echo '#ifndef FUNCNAME_H' >$(FUNCNAME_H)
  20.         echo '#define FUNCNAME_H' >>$(FUNCNAME_H)
  21.         for func in $(FUNC) ;\
  22.         do\
  23.                 echo -n '#define ' $$func  '"' >>$(FUNCNAME_H);\
  24.                 nm $(SO) | grep $$func |grep -w T| awk '{printf "%s",$$3}'>>$(FUNCNAME_H);\
  25.                 echo '"' >>$(FUNCNAME_H);\
  26.         done
  27.         echo '#endif' >>$(FUNCNAME_H)

  28. .c.o:
  29.         $(CC) -c $(CFLAGS) $< -o $@
  30. .cc.o:
  31.         $(CXX) -c $(CPPFLAGS) $< -o $@
  32. clean:
  33.         rm -f *.o $(SO) $(EXC) $(FUNCNAME_H)
复制代码

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
3 [报告]
发表于 2007-11-03 02:49 |只看该作者
测试环境

  1. linux-0gt0:/tmp/fuck # uname -a
  2. Linux linux-0gt0 2.6.16.21-0.8-default #1 Mon Jul 3 18:25:39 UTC 2006 i686 i686 i386 GNU/Linux
  3. linux-0gt0:/tmp/fuck # gcc --version
  4. gcc (GCC) 4.1.0 (SUSE Linux)
  5. Copyright (C) 2006 Free Software Foundation, Inc.
  6. This is free software; see the source for copying conditions.  There is NO
  7. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

复制代码

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
4 [报告]
发表于 2007-11-03 03:27 |只看该作者
再给出一个链接版本的,1.cc,2.cc,1.h不变,3.c,Makefile见下
3.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "funcname.h"
  4. int func(int);
  5. int main()
  6. {
  7.         int i;
  8.         i=myfunc(1);
  9.         printf("%d\n",i);
  10.         return 0;
  11. }
复制代码


Makefile

  1. CC=gcc
  2. CXX=g++
  3. FUNCNAME_H=funcname.h
  4. FUNC=myfunc
  5. C_SRC:=$(wildcard *.c)
  6. CPP_SRC:=$(wildcard *.cc)
  7. SRC:=$(C_SRC) $(CPP_SRC)
  8. C_OBJ:=$(C_SRC:.c=.o)
  9. CPP_OBJ:=$(CPP_SRC:.cc=.o)
  10. OBJ:=$(CPP_OBJ) $(C_OBJ)
  11. EXC=a.out

  12. .PHONY : all  clean
  13. all: $(EXC)
  14.         echo $(CPP_OBJ)
  15.         echo $(C_OBJ)
  16.         echo $(OBJ)
  17. $(EXC): $(OBJ)
  18.         $(CC) $(OBJ) -lstdc++ -o $(EXC)

  19. $(FUNCNAME_H):$(CPP_OBJ)
  20.         echo '#ifndef FUNCNAME_H' >$(FUNCNAME_H)
  21.         echo '#define FUNCNAME_H' >>$(FUNCNAME_H)
  22.         for func in $(FUNC) ;\
  23.         do\
  24.                 echo -n '#define ' $$func ' ' >>$(FUNCNAME_H);\
  25.                 nm $(CPP_OBJ) | grep $$func |grep -w T| awk '{printf "%s\n",$$3}'>>$(FUNCNAME_H);\
  26.         done
  27.         echo '#endif' >>$(FUNCNAME_H)

  28. %.o:%.c $(FUNCNAME_H)
  29.         $(CC) -c $(CFLAGS) $< -o $@
  30. .cc.o:
  31.         $(CXX) -c $(CPPFLAGS) $< -o $@
  32. clean:
  33.         rm -f *.o $(SO) $(EXC) $(FUNCNAME_H)
复制代码

论坛徽章:
0
5 [报告]
发表于 2007-11-03 07:59 |只看该作者

如果你有兴趣,看看这里是怎么调用的。

论坛徽章:
0
6 [报告]
发表于 2007-11-04 20:36 |只看该作者
http://bbs.chinaunix.net/viewthr ... =c%20faq&page=2

趁五一整理了一份FAQ,新手看一下

Q:c能调用c++封装的动态库吗?
A:可以,使用dlopen , dlsym 和 extern "C"
下面是个简单的例程:

QUOTE:
[root@localhost dlopen]# ls
chello.cpp  hello.cpp  include  main.c
[root@localhost dlopen]# cat include/hello.h
#ifndef _HELLO_H_
#define _HELLO_H_

class CHello
{
public:
        CHello();
        ~CHello();
        int Print();
};

#endif
[root@localhost dlopen]# cat hello.cpp
#include "hello.h"
#include <iostream>;

CHello::CHello()
{

}

CHello::~CHello()
{

}

int CHello:rint()
{
        std::cerr << "hello world !" << std::endl;
}
[root@localhost dlopen]# cat chello.cpp
extern "C"
{
        #include "hello.h"

        int cprint()
        {
                CHello * phello;
                (void *)phello =  (void *)new CHello ;

                (void *)phello->; Print();

                return 0;
        }
}
[root@localhost dlopen]# cat main.c
//#include "chello.h"
#include <dlfcn.h>;
#include <stdio.h>;
#include <stdlib.h>;
int cprint();

int
main ()
{
  char *error;
  void *handle = dlopen ("libhello.so", RTLD_NOW);
  if (!handle)
    {
      fprintf (stderr, "%s\n", dlerror ());
      exit (1);
    }

  int (*dlprint)() ;
  (void *)dlprint = dlsym (handle, "cprint";
  if ((error = dlerror ()) != NULL)
    {
      fprintf (stderr, "%s\n", error);
      exit (1);
    }

  (*dlprint)();

  dlclose (handle);


  return 0;
}
[root@localhost dlopen]# g++ -I./include -c hello.cpp
[root@localhost dlopen]# g++ -I./include -c chello.cpp
[root@localhost dlopen]# g++ -fPIC -shared -o libhello.so  hello.o chello.o
[root@localhost dlopen]# gcc  -I./include -o main main.c  -lhello -ldl
[root@localhost dlopen]# ls
chello.cpp  chello.o  hello.cpp  hello.o  include  libhello.so  main  main.c
[root@localhost dlopen]# ./main
hello world !
[root@localhost dlopen]#

论坛徽章:
0
7 [报告]
发表于 2007-11-04 20:39 |只看该作者
我现在更关心的一个问题是:
如何用纯C实现 c++的继承和多态

论坛徽章:
3
2015年迎新春徽章
日期:2015-03-04 09:56:11数据库技术版块每日发帖之星
日期:2016-08-03 06:20:00数据库技术版块每日发帖之星
日期:2016-08-04 06:20:00
8 [报告]
发表于 2007-11-04 22:20 |只看该作者
原帖由 benlan 于 2007-11-4 20:39 发表
我现在更关心的一个问题是:
如何用纯C实现 c++的继承和多态

用C就要像C,你用C来实现C++的继承和多态,我只能说,你选错了工具

论坛徽章:
0
9 [报告]
发表于 2007-11-07 00:27 |只看该作者
原帖由 cjaizss 于 2007-11-4 22:20 发表

用C就要像C,你用C来实现C++的继承和多态,我只能说,你选错了工具



有的时候,你要考虑平台性和移植性,你只能用c,但又要考虑业务的变化性,只能用c来完成面向对象的功能。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2008-04-04 10:43 |只看该作者
C用union可以实现继承,用函数指针可以实现多态
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP