【问题标题】:using C++ with namespace in C在 C 中使用带有命名空间的 C++
【发布时间】:2013-09-27 12:47:25
【问题描述】:

在 Linux 上使用 Eclpse 我定义了一个 C++ 类,命名为 ABC (ABC.hpp):

#ifndef ABC_HPP_
#define ABC_HPP_

#include <stdio.h>

// namespace my {            <---- COMMENTED OUT

class ABC {
private:
    int m_number;
public:
    ABC(int p_number);
    void doSomething();
    virtual ~ABC();
};

// } /* namespace my */      <---- COMMENTED OUT

#endif /* ABC_HPP_ */

它的实现是(ABC.cpp):

#include "ABC.hpp"

// using namespace my;       <---- COMMENTED OUT

ABC::ABC(int p_number) {
    this->m_number = p_number;
}

ABC::~ABC() {
    this->m_number = -1;
}

void ABC::doSomething() {
    printf("doing something (%d)\n", this->m_number);
}

为了在 C 程序中使用这个类,我创建了一个包含这些方法的层 (ABCwrapper.h):

typedef void CABC;

#ifdef __cplusplus
extern "C" {
#endif

CABC* create_abc();
void call_abc_methods(const CABC *p_abc);
void destroy_abc(CABC *p_abc);

#ifdef __cplusplus
} // extern "C"
#endif

#include "ABC.hpp"
#include "ABCWrapper.h"

extern "C" {

CABC* create_abc() {
    ABC* abc = new ABC();
    return (ABC*)abc;
}

void call_abc_methods(const CABC *p_abc) {
    ABC* abc = (ABC*)p_abc;
    abc->doSomething();
}

void destroy_abc(CABC *p_abc) {
    ABC* abc = (ABC*)p_abc;
    delete abc;
}

}

没关系,我可以使用 ABC 类实例。但是如何在名称空间中定义 ABC 类,比如说“我的”?如果我从所有名称空间行中删除注释符号,IDE 会抱怨说“无法解析类型 'ABC'”。

如果我想扩展我的 C++ 库,我必须为我的类使用名称空间,但我不知道如何在包装器中使用。请帮我解开这个谜。

谢谢。

SK

【问题讨论】:

  • 你能不能在 ABCWrapper.cpp 中用 my::ABC 替换 ABC 吗?
  • 您最好引入一个不完整的类型typedef struct CABC CABC;(代替typedef void CABC;),以便在C 代码中获得一些类型安全性?例如,这将阻止您将随机的FILE * 传递给 C 接口函数,而使用 void 则不会。您必须使用 reinterpret_cast&lt;ABC *&gt;(abc),但这样做而不是 C 风格的演员表会在 call_abc_methods() 函数中显示 const-ness 问题。

标签: c++ c namespaces


【解决方案1】:

ABCWrapper.cppextern "C" { 行上方,添加:

using my::ABC;

using namespace my;

john 的建议(将ABCWrapper.cpp 中的所有ABC 实例替换为my::ABC)也有效。

【讨论】:

    【解决方案2】:

    您必须为您的 ABC 课程设置范围。所以把所有的 ABC 类替换为 my::ABC 除了类声明。

      extern "C" {
    
      CABC* create_abc() {
           my::ABC* abc = new my::ABC();
           return (my::ABC*)abc;
      }
    
      void call_abc_methods(const CABC *p_abc) {
         my::ABC* abc = (my::ABC*)p_abc;
         abc->doSomething();
      }
    
      void destroy_abc(CABC *p_abc) {
          my::ABC* abc = (my::ABC*)p_abc;
          delete abc;
      }
    
    }
    

    【讨论】:

      【解决方案3】:

      关于代码的一些主要是次要的挑剔。您已经了解了具有活动命名空间的解决方案的详细信息,但还有一些小问题需要解决。

      你最好引入一个不完整的类型typedef struct CABC CABC;(代替typedef void CABC;),这样你就可以在C代码中获得一些类型安全。这将阻止您将随机的 FILE * 传递给 C 接口函数,而使用 void 则不会。

      当您使用不完整类型时,您应该在 C 包装函数中使用 reinterpret_cast&lt;ABC *&gt;(abc) 而不是 C 样式的强制转换。然后编译器会在call_abc_methods() 函数中显示常量问题;参数不应该是const(但 C 风格的演员隐藏了问题)。

      此外,您的ABC.hpp 标头显示了一个常见(小)错误;它包括一个无关的标头 (#include &lt;stdio.h&gt;),安全使用标头不需要该标头。该行应该只出现在实现文件ABC.cpp 中,其中代码使用&lt;stdio.h&gt; 的服务。大多数标头应该#include 只有那些使标头可以自己使用的其他标头。它们不应包含随机的其他标头。

      这是一个完整的工作程序——它有很多文件。有3个标题:

      • ABC.hpp — 声明 class ABC
      • ABCwrapper.h — 将 C 接口声明为 class ABC
      • ABCprogram.h — 声明其他功能的双语标头。

      有1个C文件:

      • ABCuser.c — 必须有一些 C 代码需要使用 class ABC 的 C 接口才能使整个练习变得有价值,就是这样。

      有 3 个 C++ 文件:

      • ABC.cpp — 定义 class ABC
      • ABCwrapper.cpp — 定义 class ABC 的 C 接口。
      • ABCmain.cpp — 双语系统中的主程序通常应该用 C++ 编写。

      还有一个makefile

      ABC.hpp

      #ifndef ABC_HPP_INCLUDED
      #define ABC_HPP_INCLUDED
      
      namespace abc_library {
      
      class ABC {
      private:
          int m_number;
      public:
          ABC(int p_number);
          void doSomething();
          virtual ~ABC();
      };
      
      } /* namespace abc_library */
      
      #endif /* ABC_HPP_INCLUDED */
      

      ABCwrapper.h

      #ifndef ABCWRAPPER_H_INCLUDED
      #define ABCWRAPPER_H_INCLUDED
      
      typedef struct CABC CABC;   // Pointer to this ncomplete type used in C code
      
      #ifdef __cplusplus
      extern "C" {
      #endif
      
      CABC *create_abc(int val);
      void call_abc_methods(CABC *p_abc);
      void destroy_abc(CABC *p_abc);
      
      #ifdef __cplusplus
      }
      #endif
      
      #endif /* ABCWRAPPER_H_INCLUDED */
      

      ABCprogram.h

      #ifndef ABCPROGRAM_H_INCLUDED
      #define ABCPROGRAM_H_INCLUDED
      
      #if defined(__cplusplus)
      extern "C" {
      #endif
      
      extern int c_code_function(int init);
      
      #if defined(__cplusplus)
      }
      #endif
      
      #endif /* ABCPROGRAM_H_INCLUDED */
      

      ABCuser.c

      #include "ABCwrapper.h"
      #include "ABCprogram.h"
      
      int c_code_function(int init)
      {
          CABC *abc = create_abc(init);
          call_abc_methods(abc);
          destroy_abc(abc);
          return 0;
      }
      

      ABC.cpp

      #include "ABC.hpp"
      #include <stdio.h>
      
      using namespace abc_library;
      
      ABC::ABC(int p_number) {
          this->m_number = p_number;
      }
      
      ABC::~ABC() {
          this->m_number = -1;
      }
      
      void ABC::doSomething() {
          printf("doing something (%d)\n", this->m_number);
      }
      

      ABCwrapper.cpp

      #include "ABC.hpp"
      #include "ABCwrapper.h"
      
      using namespace abc_library;
      
      extern "C" {
      
      CABC *create_abc(int val) {
          ABC* abc = new ABC(val);
          return reinterpret_cast<CABC*>(abc);
      }
      
      void call_abc_methods(CABC *p_abc) {
          ABC *abc = reinterpret_cast<ABC *>(p_abc);
          abc->doSomething();
      }
      
      void destroy_abc(CABC *p_abc) {
          ABC* abc = reinterpret_cast<ABC *>(p_abc);
          delete abc;
      }
      
      }
      

      ABCmain.cpp

      #include "ABCprogram.h"
      
      int main()
      {
         return c_code_function(39);
      }
      

      制作文件

      CC     = gcc # /usr/bin/gcc
      CXX    = g++
      RM_FR  = rm -fr --
      WFLAGS = -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition
      SFLAGS = -std=c99
      OFLAGS = -g -O3
      UFLAGS = # Set on make command line only
      
      OXXFLAGS = -g -O3
      SXXFLAGS = -std=c++11
      WXXFLAGS = -Wall -Wextra
      UXXFLAGS = # Set on make command line only
      
      LDFLAGS =
      LDLIBS  =
      
      CFLAGS   = ${OFLAGS}   ${SFLAGS}   ${WFLAGS}   ${UFLAGS}
      CXXFLAGS = ${OXXFLAGS} ${SXXFLAGS} ${WXXFLAGS} ${UXXFLAGS}
      
      PROGRAM = abc
      
      FILES.cpp = \
              ABC.cpp \
              ABCmain.cpp \
              ABCwrapper.cpp
      FILES.c = \
              ABCuser.c
      FILES.h = \
              ABCprogram.h \
              ABCwrapper.h
      
      FILES.o = ${FILES.cpp:.cpp=.o} ${FILES.c:.c=.o}
      
      all: ${PROGRAM}
      
      ${PROGRAM}: ${FILES.o}
              ${CXX} -o $@ ${CXXFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}
      
      clean:
              ${RM_FR} *.o *.dSYM core a.out
      
      depend:
              mkdep ${FILES.cpp} ${FILES.c}
      
      # DO NOT DELETE THIS LINE or the blank line after it -- make depend uses them.
      
      ABC.o: ABC.cpp
      ABC.o: ABC.hpp
      ABCmain.o: ABCmain.cpp
      ABCmain.o: ABCprogram.h
      ABCuser.o: ABCprogram.h
      ABCuser.o: ABCuser.c
      ABCuser.o: ABCwrapper.h
      ABCwrapper.o: ABC.hpp
      ABCwrapper.o: ABCwrapper.cpp
      ABCwrapper.o: ABCwrapper.h
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-05
        • 2015-09-15
        • 1970-01-01
        • 1970-01-01
        • 2011-03-13
        • 2011-07-15
        • 2014-07-17
        相关资源
        最近更新 更多