extern C и метод struct

Учитывая следующий код C++,

#ifdef __cplusplus
extern "C" {
#endif
        struct foo {
                void getNum() { 
                }
        };
#ifdef __cplusplus
}
#endif

int main (int argc, char * const argv[]) {
        return 0 ;
}

Можно ли вызвать getNum() из C?


person Community    schedule 03.08.2011    source источник
comment
Это не будет компилироваться в C.   -  person Bertrand Marron    schedule 04.08.2011
comment
@Bertrand OP хочет скомпилировать его на C ++, но вызвать из C.   -  person David Heffernan    schedule 04.08.2011
comment
@Bertrand: цель состоит в том, чтобы вызвать функцию из кода C.   -  person    schedule 04.08.2011
comment
О, неважно, я неправильно понял это.   -  person Bertrand Marron    schedule 04.08.2011
comment
Как бы вы назвали это из Си?   -  person Martin York    schedule 04.08.2011
comment
@Martin: См. здесь - dsc.sun.com/solaris/articles/mixing. html#cpp_from_c   -  person    schedule 04.08.2011
comment
@Code: Итак, из C вы вызываете функцию C++, которая имеет связь с C. Затем функция C++ может вызывать методы объекта.   -  person Martin York    schedule 04.08.2011


Ответы (4)


Нет, так как getNum является функцией-членом, которой нет в C.

Возможное решение этой проблемы состоит в том, чтобы написать функцию C++, возвращающую экземпляр foo как foo* (где foo изменено на пустую структуру) в C (я предполагаю, что это двоичный код, скомпилированный как C++, на который C ссылается), затем есть свободная функция в C++, называемая foo_getNum или что-то в этом роде, которая принимает foo* (чье определение изменено для версии C, чтобы быть пустой), которая вызывает getNum на нем. Хотя, очевидно, это не было бы безопасно для типов (но использование foo*, даже когда foo пусто, было бы лучше, чем void* - спасибо, Дэвид).

person Seth Carnegie    schedule 03.08.2011
comment
Почему в данном случае typedef struct {} foo лучше, чем typedef void foo? - person Chris Watts; 01.11.2017

extern "C" не влияет на функцию-член: getNum() имеет связь с языком C++.

Стандарт языка C++ гласит (C++03 §7.5/4):

Связь языка C игнорируется для имен членов класса и типа функции-члена функций-членов класса.

Итак, нет, вы не можете вызывать эту функцию непосредственно из программы на C (хотя, как говорили другие, вы все равно не можете скомпилировать этот код как C, потому что C не имеет функций-членов). Конечно, возможно, что некоторые реализации могут позволить вам вызывать эту функцию из программы на C с помощью некоторого метода, специфичного для реализации.

person James McNellis    schedule 03.08.2011
comment
Намерение состоит в том, чтобы скомпилировать с C++, чтобы связать с программой C. - person ; 04.08.2011

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

person David Heffernan    schedule 03.08.2011
comment
Является ли выравнивание тем, что я описал в своем ответе? Я не слышал этого термина раньше (хотя есть много терминов, которых я раньше не слышал). - person Seth Carnegie; 04.08.2011
comment
@Seth Да, вы описываете то, что я знаю как сглаживание. Кстати, void*, пожалуй, не лучший подход. Вы можете обеспечить некоторую безопасность типов, объявив пустую структуру и работая с указателями на эту структуру. - person David Heffernan; 04.08.2011
comment
Я верю вам, есть ли статья, которую я могу прочитать, объясняющую, почему последнее безопаснее, чтобы мне не пришлось тратить ваше время, заставляя вас объяснять это? - person Seth Carnegie; 04.08.2011
comment
@Seth Где-то, без сомнения, есть. Я получил образование прямо здесь, на SO, я не могу вспомнить, кто, один из гуру uber C++. Там не так много. В C void* присваивание совместимо со всеми типами указателей, без приведения. Итак, чтобы обеспечить некоторую безопасность типов, объявите свой тип указателя так, чтобы он указывал на пустой тип структуры. Тогда вы не можете отправлять строки C в функцию C++, ожидающую объект!! - person David Heffernan; 04.08.2011
comment
@Seth Читайте здесь: developers.sun.com/solaris/articles/mixing.html и прокрутите вниз до раздела Доступ к классам C++ из C. Вы можете использовать неполные определения структур, что приятно. - person David Heffernan; 04.08.2011

Приведенный вами код не будет компилироваться в режиме C, поскольку компилятор C не поддерживает функции в структуре. Однако вы можете создать функцию на С++, которая может вызвать это и связать ее с связью C. Создайте 2 файла main.c и abc.cpp

Код для main.c

extern "C" void getNumCaller();
int main ()
{
    getNumCaller();
    return 0;
}

Код для abc.cpp

#include <iostream>

struct foo {
        void getNum() {
            std::cout << "calling getNum" << std::endl;
        }
};

extern "C" void getNumCaller()
{
    struct foo abc;
    abc.getNum();
}

Скомпилируйте код:

g++ -o abc abc.cpp main.c

и вы получите результат:

calling getNum
person Vijay Sharma    schedule 03.08.2011
comment
Это почти полезно, но getNumCaller нужно передать указатель на структуру. Это уплощение интерфейса. - person David Heffernan; 04.08.2011
comment
@david Что вы подразумеваете под сглаживанием интерфейса? Никогда не слышал об этом термине - person Vijay Sharma; 07.08.2011