2015-06-01 5 views
0

Я пытаюсь включить код C, который я нашел в нашем проекте на C++. Функция определяется как это в файле C.Ошибка компоновщика при вызове функции C из кода C++ в другом проекте VS2010

#ifdef __cplusplus 
extern "C" { 
#endif 
extern char *dtoa(double, int, int, int *, int *, char **); 
extern char *g_fmt(char *, double); 
extern void freedtoa(char*); 
#ifdef __cplusplus 
    } 
#endif 

char * 
g_fmt(register char *b, double x) 
{ 

Проект VS, в который я включаю это, создает dll. Файл компилируется как C, другие файлы в проекте компилируются как C++.

я добавил заголовок включить в моей C++ файлы

#ifndef G_FMT_H 
#define G_FMT_H 
#ifdef __cplusplus 
extern "C" { 
#endif 
extern char *dtoa(double, int, int, int *, int *, char **); 
extern char *g_fmt(char *, double); 
extern void freedtoa(char*); 

#ifdef __cplusplus 
} 
#endif 
#endif //G_FMT_H 

В другом проекте в решении я включаю мой заголовок и попытаться вызвать функцию g_fmt.

#include "header.h" 
... 
g_fmt(my_array, 2.0); 

Этот проект связан с другим, я могу вызвать функции C++ в первой библиотеке без каких-либо проблем. Однако добавление вышеприведенной строки дает мне ошибку lnk2001.

error LNK2001: unresolved external symbol g_fmt 

Я нашел ряд других вопросов о смешивании C и C++, и я, кажется, сделали все необходимое с Экстерн ключевые слова в нужных местах, но я до сих пор не в состоянии связать. Есть ли что-то конкретное, что мне нужно делать в VS2010?

+0

, поэтому вы можете использовать dtoa, но не g_fmt? – marom

+0

нет, я имею в виду, что я могу использовать функции C++, объявленные в другом месте в той же библиотеке. Я читал в других сообщениях, которые вы можете смешивать C и C++ в одном проекте, может быть, это не совсем так? – Boumbles

+0

Это правда, дело в том, как вы экспортируете функции? Обычно вам нужен __declspec (dllexport) или файл def. Какой метод вы используете здесь? – marom

ответ

2

В C или С ++, учитывая, что модуль может состоять из нескольких объектов, каждый объект должен быть четко разграничены. Кроме того, каждый объект (.c или .cpp файл) должен иметь собственный заголовочный файл. Итак, у вас должен быть один файл заголовка и один файл c (xx) для функций C (в вашем примере). Кроме того, в качестве общего руководства старайтесь быть последовательным при именовании файлов и макросов: в вашем файле header.h используется G_FMT_H макрос, который включает охрану. Итак, попробуйте реорганизовать ваш .h и .c файлы на что-то вроде:

functions.h:

#pragma once 

#if defined (WIN32) 
#if defined(FUNCTIONS_STATIC) 
#define FUNCTIONS_API 
#else 
#if defined(FUNCTIONS_EXPORTS) 
#define FUNCTIONS_API __declspec(dllexport) 
#else 
#define FUNCTIONS_API __declspec(dllimport) 
#endif 
#endif 
#else 
#define FUNCTIONS_API 
#endif 

#ifdef __cplusplus 
extern "C" { 
#endif 

    FUNCTIONS_API char *dtoa(double, int, int, int *, int *, char **); 
    FUNCTIONS_API char *g_fmt(char *, double); 
    FUNCTIONS_API void freedtoa(char*); 

#ifdef __cplusplus 
} 
#endif 

и соответствующей реализации (functions.c):

#define FUNCTIONS_EXPORTS 
#include "functions.h" 

char *dtoa(double, int, int, int *, int *, char **) { 
    //function statements 
} 

char *g_fmt(char *, double) { 
    //function statements 
} 

void freedtoa(char*) { 
    //function statements 
} 

2 примечания (кроме реорганизации и переименования) в файле заголовка:

  • Спецификатор extern хранения для каждой функции уходит
  • Экспортной логики: ваш проект будет определять в настоящее время FUNCTIONS_EXPORT (от functions.c или желательного быть установкой проекта VStudio - во всяком случае, где-то перед тем#include "functions.h")
    • Когда этот проект (функции.c), функции будут экспортироваться (из-за определения макроса)
    • Когда заголовочный файл будет включен в другой проект (который не определяет FUNCTIONS_EXPORTS), функции будут отмечены как импортированные и компоновщик будет искать их в импортированной Lib (ов) - один из них должен быть один, порожденный этим проектом
    • Чтобы быть более строгим, вы могли бы заменить FUNCTIONS_EXPORTS (и удалить его определение из functions.c) макросом автоматически#define d VStudio IDE: ${YOUR_PROJECT_NAME}_EXPORTS (например, если ваш Dll проект называется ExportFunctionsProject.vc (х) проектируемый, то имя макроса будет EXPORTFUNCTIONSPROJECT_EXPORTS)
    • Вы можете проверить имя макроса в VStudio (2010) IDE: Свойства проекта -> C/C++ -> Препроцессор -> Определения препроцессора. Для получения более подробной информации, проверьте [MSDN]: /D (Preprocessor Definitions)

Похожие (или связанных с ними) вопросы:

EDIT0: Добавлено "поддержка" для статические строит.
EDIT1: Перекрестная платформа + некоторые исправления.

 Смежные вопросы

  • Нет связанных вопросов^_^