Получение многих включает ошибки при преобразовании C в C ++ в смешанной кодовой базе - PullRequest
0 голосов
/ 21 февраля 2020

Я немного новичок в C ++ и у меня есть вопрос относительно преобразования C кода в код C ++, а также смешивания C и кода C ++.

Например, я занимаюсь рефакторингом предыдущий C файл в файл C ++, потому что теперь я должен использовать std :: string в структуре заголовочного файла. Теперь это выглядит следующим образом ( firstClass.hpp ):

struct firstClass
{
              .
              .
              .

    std::string test_string;

    firstClass();
    firstClass(const firstClass &c);
    ~firstClass();
};

И, как результат, вот первоклассный. cpp:

#include "firstClass.hpp"

extern "C"
{
              .
              .
              .

     #include <errno.h>
     #include <assert.h>
     #include <stdlib.h>
     #include <string.h>
}

              .
              .
              .

Теперь вот мой вопрос: у меня есть другие файлы, которые ранее включали firstClass.h ( Примечание: это C -вариант), прежде чем я преобразовал его в C ++ код - эти файлы также должны быть преобразованы в код C ++? Кроме того, если дополнительные файлы включают эти файлы, упомянутые выше, их также необходимо преобразовать? Я думаю, чтобы подвести итог моего вопроса: после преобразования этого исходного файла в C ++, как далеко вниз по цепочке включений мне нужно также конвертировать эти файлы?

Ответы [ 2 ]

1 голос
/ 21 февраля 2020

Большинство компиляторов C ++ обрабатывают как файлы исходного кода C, файлы с расширением. c, так и файлы исходного кода C ++, файлы с расширением. cpp. Поэтому первым шагом в преобразовании будет переход на компилятор C ++ и приведение файлов вашего проекта и / или создание файлов в порядок, чтобы все это компилировалось.

Следующее - go через исходный код кодовая база, чтобы определить, какие структуры данных будут изменены и какие файлы, обычно файлы с расширением .h, имеют эти структуры данных, которые нужно будет изменить.

На этом этапе вам нужно будет начать разбиение что такое источник C ++ и какой источник C. Например, в то время как C struct является подмножеством C ++ struct, C ++ struct допускает конструкторы и деконструкторы, которые C не позволяет. Это означает, что вы можете использовать C struct с исходным кодом C ++, но нельзя использовать C ++ struct с функциями C ++ в исходном файле C.

Другие ключевые слова языка C ++, такие как class просто не будет работать с исходным кодом C.

Далее стоит посмотреть, какие функции C ++, такие как шаблоны и функции стандартной библиотеки C ++, такие как std::string, вы собираетесь использовать. Опять же вам нужно будет отделить исходный код C ++ от C.

Функциональность extern "C" позволяет вам использовать функции C с исходным кодом C ++, объявив имя функции или переменной как C а не C ++. Это необходимо, потому что компилятор C ++ выполняет искажение имен, используя алгоритм для генерации измененного имени для функций, допускающих перегрузку функций. См. Что такое искажение имен и как оно работает?

Еще одна вещь, с которой вы столкнетесь, это то, что C ++ представил новые версии большинства стандартных C включаемых файлов без расширение .h. Вы можете использовать старую версию с C ++, но новые версии предпочтительнее, поскольку они предназначены для C ++. Однако C исходные файлы могут использовать только старую версию этих файлов с расширением .h.

Условная компиляция для заголовочных файлов

Волхвы c, которые позволяет использовать более старый стандарт C, включающий файлы с исходным кодом C ++, так как большинство компиляторов имеют специальный #define, который можно использовать для условной компиляции. С компилятором Visual Studio специальное определение - __cplusplus, и его можно использовать примерно так:

#if defined(__cplusplus)
extern "C" {
#endif

// The type CONNENGINEHANDLE is for future expansion to allow multiple
// sockets to be managed by the dll.
typedef unsigned short CONNENGINEHANDLE;

// following functions are used with a server implementation.
// these functions will setup the parameters for the server and
// start the listen needed to accept a connection from a client
CONNENGINE_API int fnConnEngineSetDomainNamePort(CONNENGINEHANDLE hConnEngineSocket, char *aszDomainName, int nPortNo);
CONNENGINE_API int fnConnEngineStartEngine (int nPort, HWND hWinHandle, UINT wReceiveMsgId);
CONNENGINE_API int fnConnEngineStopEngine ();

#if defined(__cplusplus)
};
#endif

Что делает вышеуказанный код препроцессора, являющийся частью включаемого файла, так это разрешить файл исходного кода C ++ чтобы включить тот же заголовочный файл, что и файлы исходного кода C, но когда он включен в файл C ++, extern "C" { является частью текста заголовочного файла, поскольку препроцессор определил __cplusplus. Таким образом, источник C ++ может использовать функции, определенные в исходном коде C, и искажение имени, обычно выполняемое с помощью C ++, отключено для тех функций, объявления которых заключены в фигурные скобки.

Однако, хотя это специальное #define чтобы определить, обрабатывается ли препроцессором исходный файл C ++, вы все еще не можете использовать языковые конструкции C ++ в C исходных файлах. Вам все равно нужно будет отделить C ++ от C.

Интерфейсных функций для C вызова функции C ++

В некоторых случаях вам может потребоваться выполнить Функциональность исходного кода C ++ из C функциональность исходного кода. В этих случаях вам потребуется создать C совместимый интерфейс с функциями C ++.

Например, если у вас есть struct, который содержит std::string, что несовместимо с исходным кодом C Вы можете создать исходный код C ++, чтобы скрыть детали реализации и затем предоставить C совместимый интерфейс.

Например, из примера включаемого файла, демонстрирующего использование __cplusplus выше, одна из этих функций определяется в файле исходного кода C ++ следующим образом. Этот файл исходного кода C ++ также содержит тот же заголовочный файл, который будет использоваться с файлом исходного кода C и с объявлением выше для функции fnConnEngineStartEngine(), компилятор C ++ знает, что он не должен называть mangle имя функции fnConnEngineStartEngine{}. Этот исходный код C ++ обеспечивает интерфейс между источником C, который использует объект C ++ theApp.

CONNENGINE_API int fnConnEngineStartEngine (int nPort, HWND hWinHandle, UINT wReceiveMsgId)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    if (hWinHandle == 0)
        hWinHandle = theApp.m_hWinHandle;

    if (wReceiveMsgId == 0)
        wReceiveMsgId = theApp.m_wReceiveMsgId;

    theApp.StartEngineAsServer (nPort, hWinHandle, wReceiveMsgId);
    return 0;
}
0 голосов
/ 21 февраля 2020

Что вы хотите сделать, это использовать компилятор C ++ для кода C. Компилятор C ++ будет прекрасно обрабатывать код C и обрабатывать синтаксис C ++.

Не уверен, какой компилятор или IDE вы используете. Это может быть сделано для многих компиляторов путем добавления аргумента в командной строке или для создания параметров. Или с помощью параметра в настройках компилятора для IDE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...