7

Linux で Eclpse を使用して、ABC (ABC.hpp) という名前の C++ クラスを定義しました。

#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 クラスを定義するのはどうでしょうか。たとえば、"my" としましょう。すべての名前空間行からコメント記号を削除すると、IDE は「タイプ 'ABC' を解決できませんでした」と不平を言います。

C++ ライブラリを拡張したい場合、クラスに名前空間を使用する必要がありますが、ラッパーで使用する方法がわかりません。この謎を解くのを手伝ってください。

ありがとうございました。

SK

4

3 に答える 3

6

コードに関するいくつかの主にマイナーな問題点。アクティブな名前空間を使用したソリューションの詳細については既に説明しましたが、対処すべきさまざまな小さな問題があります。

typedef struct CABC CABC;( の代わりにtypedef void CABC;) 不完全な型を導入して、C コードで型の安全性を確保する方がよいでしょう。FILE *これにより、たとえば、使用しない C インターフェイス関数にrandom を渡すことvoidができなくなります。

不完全型を使用する場合reinterpret_cast<ABC *>(abc)は、C スタイルのキャストではなく、C ラッパー関数で使用する必要があります。コンパイラは、call_abc_methods()関数の const-ness に問題があることを示します。引数はそうであってはなりませんconst(しかし、C スタイルのキャストが問題を隠していました)。

さらに、ABC.hppヘッダーにはよくある (マイナーな) 間違いが示されています。#include <stdio.h>ヘッダーを安全に使用するために必要のない不要なヘッダー ( ) が含まれています。ABC.cppその行は、コードが のサービスを使用する実装ファイル にのみ表示されます<stdio.h>。ほとんどのヘッダーは#include、ヘッダーを単独で使用できるようにするために必要な他のヘッダーのみにする必要があります。ランダムな他のヘッダーを含めるべきではありません。

これは完全に機能するプログラムです — これには多くのファイルがあります。3 つのヘッダーがあります。

  • ABC.hpp—宣言するclass ABC
  • ABCwrapper.h— への C インターフェイスを宣言しますclass ABC
  • ABCprogram.h— 他の機能を宣言するバイリンガル ヘッダー。

1 つの C ファイルがあります。

  • ABCuser.cclass ABC—演習全体をやりがいのあるものにするために、C インターフェイスを使用する必要がある C コードがいくつかあるに違いありません。これで終わりです。

3 つの C++ ファイルがあります。

  • ABC.cpp— 定義しclass ABCます。
  • ABCwrapper.cpp— への C インターフェイスを定義しますclass ABC
  • 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
于 2013-09-23T00:19:03.777 に答える
5

ABCWrapper.cppの行の上にextern "C" {、次を追加します。

using my::ABC;

また

using namespace my;

ABCジョンの提案 (のすべてのインスタンスをmy::ABCin に置き換えるABCWrapper.cpp) も機能します。

于 2013-09-22T15:27:48.187 に答える
1

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;
  }

}
于 2013-09-22T15:55:24.167 に答える