• 联系我们
  • 地址:湖北武汉三环科技园
  • 电话:159116031100
  • 传真:027-68834628
  • 邮箱:mmheng@foxmail.com
  • 当前所在位置:首页 - c++培训
  • 在C程序中调用C语言代码的过程c语言
  •   如果要你写一个处理C++程序使之能够被C编译器接受的程序,应该从哪些方面考虑?

      现在在做Open64的编译器项目,里面有一堆80年代SGI写的C代码,现在要加入一些新的代码。我用C++写新的代码,然后试图在C程序中调用,结果出错,在网上搜索半天,终于找到解决办法,这里总结一下。

      C与C++的区别主要是C不支持类(Class),不支持函数重载(function overloading),当然模板(template)也是不支持的。所以要在C程序中调用C++代码,最重要的原则就是给C程序提供一个C程序可用的接口。

      规则一:接口中不能涉及类,以及引用

      class A{…};

      A foo(); // 这个函数是不能被C程序调用的,因为C程序不能识别A

      void foo(A); // 这个也不行,道理同上

      void foo(const int // 同样不行,C不能识别引用

      void foo(int n); // 这个就可以

      规则二:接口中不能有重名函数

      因为C中没有函数重载这个概念,同名的函数会被当做同一个函数,即使他们的参数不一样,所以在C程序调用的接口中,不能有重名的函数。如果你有两个函数 foo(int)和foo(double),那么就必须将这两个函数改名,以便使C程序能够区别他们,比如将两个函数分别命名为 foo_int(int)和foo_double(double)。

      规则三:接口需要用 extern C来声明

      这个规则需要解释一下。C++允许函数重载,也就是说你可以同时声明 foo(int) 和foo(double),这两个函数是同名的,但实际在编译时编译器会给这两个函数生成不同的名字,以供区别,比如foo(int)可能对应成foo12345(12345是随机生成的),而foo(double)对应成foo34532.在不存在函数重载的情况下,编译器仍然会给这些函数重命名。而在C语言中,因为没有函数重载,所以也不存在函数重命名的情况。

      比如说,我们写了一个C++程序,里面包含函数foo(int),我们将这个程序编译成 a.o.同时我们还写了一个C程序,里面调用了这个函数,我们将它编译为 b.o.在链接a.o和b.o的过程中,编译器会提示你找不到foo(int)这个函数的定义。因为在a.o里,foo很可能已经被重命名为foox,而b.o里的函数名却依旧是foo,编译器会试图在a.o里查找foo,当然就会失败。

      extern C正是用来解决这种情况的。只要将 foo(int)的声明写成:

      extern C foo(int)

      编译器就不会对这个函数重命名,从而避免了上述错误的发生。

      规则四:用 #ifdef __cplusplus 来避免编译失败

      有时候我们会在。h文件中加入类定义。但是对C程序来说,类是不可识别的。因此如果我们在一个C文件里包含这样的。h文件,就会碰到编译不通过的问题。

      比如一个A.h文件如下:

      // A.h

      class A{

      public:

      void foo();

      //…

      };

      extern C invokeA();

      B.c文件如下:

      #include A.h

      int main(){

      invokeA();

      //…

      }

      这样就会出现B.c文件无法编译的情况。要解决这种情况,只需要将A.h改成:

      #ifdef __cplusplus

      // A.h

      class A{

      public:

      void foo();

      //…

      };

      #endif

      extern C invokeA();

      这样当B.c包含A.h时,编译器处理到#ifdef __cplusplus时发现判断结果为假,就自动忽略了下面的内容,B.c就能编译通过了。

      同时我们看到,这里有个invokeA()函数,它的作用就是调用A中的foo函数。也就是说,invokeA只是A::foo的一个包装。实际上,在C函数中要调用类的函数,也只能通过这样的包装。

      在如今这个信息爆炸的时代里,每天都会有数不清的新闻通过各种渠道涌到我们面前,而真正有价值的应该进入我们心里的,却很可能随着日历牌的翻动被我们忽略。作为对一周新闻进行回顾的《比特网新闻中心每周热点推荐》,就是要告诉您过去的七天都发生了哪些新闻,更希望和您一起,站在七天的高度来看待过去一周的新闻

      业内首个只为报道数据中心资讯内容的专业频道,是为数据中心用户及厂商而建设的专业平台。以数据中心专业技术内容为核心,贯穿新鲜资讯、技巧方法和用户案例等高附加值内容。以为网友提供最具实用价值的信息为原则,以成为用户最信赖的行业专家为目标,打造高时效、高品质、高前瞻的最全威频道。企业数据中心热点播报,为您精心奉上过去一周数据中心最精彩、权威资讯_chinabyte比特网。

      就服务器和数据中心领域的产业动态、技术热点、热产品、实用技巧,向企业CIO/CTO、IT管理层、技术人员提供一周精选套餐,为数据中心决策者、使用者提供一份服务器行业以及数据中心领域最新动态及产品应用的技术套餐。

      如果要你写一个处理C++程序使之能够被C编译器接受的程序,应该从哪些方面考虑?

      现在在做Open64的编译器项目,里面有一堆80年代SGI写的C代码,现在要加入一些新的代码。我用C++写新的代码,然后试图在C程序中调用,结果出错,在网上搜索半天,终于找到解决办法,这里总结一下。

      C与C++的区别主要是C不支持类(Class),不支持函数重载(function overloading),当然模板(template)也是不支持的。所以要在C程序中调用C++代码,最重要的原则就是给C程序提供一个C程序可用的接口。

      规则一:接口中不能涉及类,以及引用

      class A{…};

      A foo(); // 这个函数是不能被C程序调用的,因为C程序不能识别A

      void foo(A); // 这个也不行,道理同上

      void foo(const int // 同样不行,C不能识别引用

      void foo(int n); // 这个就可以

      规则二:接口中不能有重名函数

      因为C中没有函数重载这个概念,同名的函数会被当做同一个函数,即使他们的参数不一样,所以在C程序调用的接口中,不能有重名的函数。如果你有两个函数 foo(int)和foo(double),那么就必须将这两个函数改名,以便使C程序能够区别他们,比如将两个函数分别命名为 foo_int(int)和foo_double(double)。

      规则三:接口需要用 extern C来声明

      这个规则需要解释一下。C++允许函数重载,也就是说你可以同时声明 foo(int) 和foo(double),这两个函数是同名的,但实际在编译时编译器会给这两个函数生成不同的名字,以供区别,比如foo(int)可能对应成foo(是随机生成的),而foo(double)对应成foo.在不存在函数重载的情况下,编译器仍然会给这些函数重命名。而在C语言中,因为没有函数重载,所以也不存在函数重命名的情况。

      比如说,我们写了一个C++程序,里面包含函数foo(int),我们将这个程序编译成 a.o.同时我们还写了一个C程序,里面调用了这个函数,我们将它编译为 b.o.在链接a.o和b.o的过程中,编译器会提示你找不到foo(int)这个函数的定义。因为在a.o里,foo很可能已经被重命名为foox,而b.o里的函数名却依旧是foo,编译器会试图在a.o里查找foo,当然就会失败。

      extern C正是用来解决这种情况的。只要将 foo(int)的声明写成:

      extern C foo(int)

      编译器就不会对这个函数重命名,从而避免了上述错误的发生。

      规则四:用 #ifdef __cplusplus 来避免编译失败

      有时候我们会在。h文件中加入类定义。但是对C程序来说,类是不可识别的。因此如果我们在一个C文件里包含这样的。h文件,就会碰到编译不通过的问题。

      比如一个A.h文件如下:

      // A.h

      class A{

      public:

      void foo();

      //…

      };

      extern C invokeA();

      B.c文件如下:

      #include A.h

      int main(){

      invokeA();

      //…

      }

      这样就会出现B.c文件无法编译的情况。要解决这种情况,只需要将A.h改成:

      #ifdef __cplusplus

      // A.h

      class A{

      public:

      void foo();

      //…

      };

      #endif

      extern C invokeA();

      这样当B.c包含A.h时,编译器处理到#ifdef __cplusplus时发现判断结果为假,就自动忽略了下面的内容,B.c就能编译通过了。

      同时我们看到,这里有个invokeA()函数,它的作用就是调用A中的foo函数。也就是说,invokeA只是A::foo的一个包装。实际上,在C函数中要调用类的函数,也只能通过这样的包装。

      在如今这个信息爆炸的时代里,每天都会有数不清的新闻通过各种渠道涌到我们面前,而真正有价值的应该进入我们心里的,却很可能随着日历牌的翻动被我们忽略。作为对一周新闻进行回顾的《比特网新闻中心每周热点推荐》,就是要告诉您过去的七天都发生了哪些新闻,更希望和您一起,站在七天的高度来看待过去一周的新闻

      业内首个只为报道数据中心资讯内容的专业频道,是为数据中心用户及厂商而建设的专业平台。以数据中心专业技术内容为核心,贯穿新鲜资讯、技巧方法和用户案例等高附加值内容。以为网友提供最具实用价值的信息为原则,以成为用户最信赖的行业专家为目标,打造高时效、高品质、高前瞻的最全威频道。企业数据中心热点播报,为您精心奉上过去一周数据中心最精彩、权威资讯_chinabyte比特网。

      就服务器和数据中心领域的产业动态、技术热点、热产品、实用技巧,向企业CIO/CTO、IT管理层、技术人员提供一周精选套餐,为数据中心决策者、使用者提供一份服务器行业以及数据中心领域最新动态及产品应用的技术套餐。