Пространства имен в C -- c++ поле с участием c поле с участием namespaces поле с участием c-preprocessor пол Связанный проблема

Namespaces in C


58
vote

проблема

русский

Есть ли способ (ab) использовать препроцессор c для эмуляции пространств имен в c ?

Я думаю что-то по этим строкам:

 <код> #define NAMESPACE name_of_ns some_function() {     some_other_function(); }   

Это будет переведено на:

 <код> name_of_ns_some_function() {     name_of_ns_some_other_function(); }   
Английский оригинал

Is there a way to (ab)use the C preprocessor to emulate namespaces in C?

I'm thinking something along these lines:

#define NAMESPACE name_of_ns some_function() {     some_other_function(); } 

This would get translated to:

name_of_ns_some_function() {     name_of_ns_some_other_function(); } 
</div
           

Список ответов

53
 
vote
vote
Лучший ответ
 
<Р> При использовании префиксов пространства имен, я обычно добавлять макросы для сокращенных имен, которые могут быть активированы с помощью <код> #define NAMESPACE_SHORT_NAMES перед включением заголовка. Foobar.h заголовок может выглядеть следующим образом:
 <код> // inclusion guard #ifndef FOOBAR_H_ #define FOOBAR_H_  // long names void foobar_some_func(int); void foobar_other_func();  // short names #ifdef FOOBAR_SHORT_NAMES #define some_func(...) foobar_some_func(__VA_ARGS__) #define other_func(...) foobar_other_func(__VA_ARGS__) #endif  #endif   
<Р> Если я хочу использовать короткие имена в том числе файл, я буду делать
 <код> #cd .git #rm index #cd .. #git add . 0  
<Р> Я найти это более чистый и более полезное решение, чем использование пространства имен макросов, как описано Винко Vrsalovic (в комментарии).
 

When using namespace prefixes, I normally add macros for the shortened names which can be activated via #define NAMESPACE_SHORT_NAMES before inclusion of the header. A header foobar.h might look like this:

// inclusion guard #ifndef FOOBAR_H_ #define FOOBAR_H_  // long names void foobar_some_func(int); void foobar_other_func();  // short names #ifdef FOOBAR_SHORT_NAMES #define some_func(...) foobar_some_func(__VA_ARGS__) #define other_func(...) foobar_other_func(__VA_ARGS__) #endif  #endif 

If I want to use short names in an including file, I'll do

#define FOOBAR_SHORT_NAMES #include "foobar.h" 

I find this a cleaner and more useful solution than using namespace macros as described by Vinko Vrsalovic (in the comments).

</div
 
 
 
 
86
 
vote
<Р> Другой альтернативой было бы объявить-структуру, чтобы держать все свои функции, а затем определить свои функции статически. Тогда вы должны только беспокоиться о конфликтах имен для глобального имени структуры.
 <код> #cd .git #rm index #cd .. #git add . 1  
<Р> В приведенном выше примере, <код> #cd .git #rm index #cd .. #git add . 2 и <код> #cd .git #rm index #cd .. #git add . 3 не может быть вызван непосредственно из main.c, только через <код> #cd .git #rm index #cd .. #git add . 4 . <Р> Если у вас есть куча имен, декларирующих функции с теми же подписями, то вы можете стандартизировать ваше пространство имен структура для этого набора, и выберите пространство имен для использования во время выполнения.
 <код> #cd .git #rm index #cd .. #git add . 5  
<Р> Несколько определений <код> #cd .git #rm index #cd .. #git add . 6 и <код> #cd .git #rm index #cd .. #git add . 7 не противоречат друг другу, так как они определены статически, но основные функции по-прежнему доступны через соответствующее пространство имен структуры. < / р>
 

Another alternative would be to declare a struct to hold all your functions, and then define your functions statically. Then you'd only have to worry about name conflicts for the global name struct.

// foo.h #ifndef FOO_H #define FOO_H typedef struct {    int (* const bar)(int, char *);   void (* const baz)(void); } namespace_struct; extern namespace_struct const foo; #endif // FOO_H  // foo.c #include "foo.h" static int my_bar(int a, char * s) { /* ... */ } static void my_baz(void) { /* ... */ } namespace_struct const foo = { my_bar, my_baz }  // main.c #include <stdio.h> #include "foo.h" int main(void) {   foo.baz();   printf("%d", foo.bar(3, "hello"));   return 0; } 

In the above example, my_bar and my_baz can't be called directly from main.c, only through foo.

If you have a bunch of namespaces that declare functions with the same signatures, then you can standardize your namespace struct for that set, and choose which namespace to use at runtime.

// goo.h #ifndef GOO_H #define GOO_H #include "foo.h" extern namespace_struct const goo; #endif // GOO_H  // goo.c #include "goo.h" static int my_bar(int a, char * s) { /* ... */ } static void my_baz(void) { /* ... */ } namespace_struct const goo = { my_bar, my_baz };  // other_main.c #include <stdio.h> #include "foo.h" #include "goo.h" int main(int argc, char** argv) {   namespace_struct const * const xoo = (argc > 1 ? foo : goo);   xoo->baz();   printf("%d", xoo->bar(3, "hello"));   return 0; } 

The multiple definitions of my_bar and my_baz don't conflict, since they're defined statically, but the underlying functions are still accessible through the appropriate namespace struct.

</div
 
 
         
         
13
 
vote
<Р> Вы можете использовать оператор ##:
 <код> #cd .git #rm index #cd .. #git add . 8  
<Р> и объявлять функции, как:
 <код> #cd .git #rm index #cd .. #git add . 9  
<Р> Выглядит довольно неудобно, хотя.
 

You could use the ## operator:

#define FUN_NAME(namespace,name) namespace ## name 

and declare functions as:

void FUN_NAME(MyNamespace,HelloWorld)() 

Looks pretty awkward though.

</div
 
 
     
     
8
 
vote
<Р> я придумал следующую схему: <Р> (заголовок)
 <код> .git0  
<Р> (реализации)
 <код> .git1  
 

I came up with the following scheme :

(header)

// NS_PREFIX controls the prefix of each type and function declared in this // header, in order to avoid name collision. #define NS_PREFIX myprefix_  // Makes a string from argument (argument is not macro-expanded). #define stringify(arg) #arg  // Concatenation that macro-expands its arguments. #define concat(p1, p2) _concat(p1, p2) // Macro expands the arguments. #define _concat(p1, p2) p1 ## p2       // Do the actual concatenation.  // Append the namespace prefix to the identifier. #define ns(iden) concat(NS_PREFIX, iden)  // header content, for instance : void ns(my_function)(int arg1, ns(t) arg2, int arg3);  // Allow implementation files to use namespacing features, else // hide them from the including files. #ifndef _IMPL #undef NS_PREFIX #undef ns #undef stringify #undef concat #undef _concat #endif // _IMPL 

(implementation)

#define  _IMPL  #include "header.h" #undef   __IMPL 
</div
 
 
7
 
vote

Я использую подход на основе структур с двумя уточнениями: добавляю подструкции для создания иерархических пространств имен, и я определяю несколько простых макросов, когда я хочу упростить путь имен.

Давайте взять библиотеку FOOBAR в качестве примера.

foobar.h

 <код> #ifndef __FOOBAR_H__ #define __FOOBAR_H__  // definition of the namespace's hierarchical structure struct _foobar_namespace {     struct {         void (*print)(char *s);     } text;     struct {         char *(*getDateString)(void);     } date; };  // see the foobar.c file // it must be the only one defining the FOOBAR macro # ifndef FOOBAR     // definition of the namespace global variable     extern struct _foobar_namespace foobar; # endif // FOOBAR  #endif // __FOOBAR_H__   

<Сильные> foobar.c

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } };   

Тогда можно использовать пространство имен:

 <код> #include "foobar.h"  void main() {     foobar.text.print("it works"); }   

Но есть не так много различий между <код> foobar_text__print() и <код> foobar.text.print() . Я думаю, что второй читательнее, но это сомнительно. Таким образом, он становится действительно полезным, определение некоторых макросов для упрощения этих пространств имен:

 <код> #include "foobar.h"  #define txt    foobar.text #define date   foobar.date  void main() {     char *today = date.getDateString();     txt.print(today); }   

Этот вид иерархических пространств имен быстро определяет, легко понять и уменьшить и уменьшить многообразность кода.


Просто для удовольствия, вот файлы для <код> foobar.text код:

foobar_text.h

 <код> #ifndef __FOOBAR_TEXT_H__ #define __FOOBAR_TEXT_H__  void foobar_text__print(char *s);  #endif // __FOOBAR_TEXT_H__   

foobar_text.c.c

 <код> #include <stdio.h> #include "foobar_text.h"  void foobar_text__print(char *s) {     printf("%s ", s); }   
 

I use the struct-based approach, with two refinements: I add substructures to create hierarchical namespaces, and I define some simple macros when I want to simplify namespaces' path.

Let's take a Foobar library as an example.

foobar.h

#ifndef __FOOBAR_H__ #define __FOOBAR_H__  // definition of the namespace's hierarchical structure struct _foobar_namespace {     struct {         void (*print)(char *s);     } text;     struct {         char *(*getDateString)(void);     } date; };  // see the foobar.c file // it must be the only one defining the FOOBAR macro # ifndef FOOBAR     // definition of the namespace global variable     extern struct _foobar_namespace foobar; # endif // FOOBAR  #endif // __FOOBAR_H__ 

foobar.c

// the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 

Then, it's possible to use the namespace:

#include "foobar.h"  void main() {     foobar.text.print("it works"); } 

But there is not so much difference between foobar_text__print() and foobar.text.print(). I think the second one is more readable, but it's questionable. So it become really useful by defining some macros to simplify these namespaces:

#include "foobar.h"  #define txt    foobar.text #define date   foobar.date  void main() {     char *today = date.getDateString();     txt.print(today); } 

This kind of hierarchical namespaces is fast to define, easy to understand, and decrease code verbosity.


Just for fun, here are the files for foobar.text code:

foobar_text.h

#ifndef __FOOBAR_TEXT_H__ #define __FOOBAR_TEXT_H__  void foobar_text__print(char *s);  #endif // __FOOBAR_TEXT_H__ 

foobar_text.c

#include <stdio.h> #include "foobar_text.h"  void foobar_text__print(char *s) {     printf("%s ", s); } 
</div
 
 
4
 
vote

Я записал учебное пособие по вопросам того, как получить преимущество пространств имен и / или шаблонов, использующих C.

Пространства и шаблоны и шаблоны в C

Пространства имен и Шаблоны в C (используя связанные списки)

Для базового пространства имен можно просто префикнуть имя пространства имен в качестве Конвенции.

 <код> namespace MY_OBJECT {   struct HANDLE;   HANDLE *init();   void destroy(HANDLE * & h);    void do_something(HANDLE *h, ... ); }   

можно записать как

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 0  

Второй подход, который я должен был использовать, что использует концепцию пространства и шаблонов и шаблонов, заключается в использовании Concateenation Macro и включения. Например, я могу создать

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 1  

Использование файлов шаблонов следующим образом

Multiply-template.h

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 2  

Multiply-template.c

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 3  

Теперь мы можем определить int_multipliply следующим образом. В этом примере я создам файл int_multiply.h / .c.

int_multiply.h

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 4  

int_multiply.c

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 5  

В конце всего этого у вас будет файл функции и заголовка.

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 6  

Я создал гораздо более подробный учебник по предоставленным ссылкам. Надеюсь, это поможет кому-то!

 

I wrote up a tutorial on how to get the advantage of namespaces and/or templates using C.

Namespaces and templates in C

Namespaces and templates in C (using Linked Lists)

For the basic namespace, one can simply prefix the namespace name as a convention.

namespace MY_OBJECT {   struct HANDLE;   HANDLE *init();   void destroy(HANDLE * & h);    void do_something(HANDLE *h, ... ); } 

can be written as

struct MY_OBJECT_HANDLE; struct MY_OBJECT_HANDLE *my_object_init(); void my_object_destroy( MY_OBJECT_HANDLE * & h );  void my_object_do_something(MY_OBJECT_HANDLE *h, ... ); 

A second approach that I have needed that uses the concept of namespacing and templates is to use the macro concatenation and include. For example, I can create a

template<T> T multiply<T>( T x, T y ) { return x*y } 

using template files as follows

multiply-template.h

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y); 

multiply-template.c

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {   return x*y; } 

We can now define int_multiply as follows. In this example, I'll create a int_multiply.h/.c file.

int_multiply.h

#ifndef _INT_MULTIPLY_H #define _INT_MULTIPLY_H  #ifdef _multiply_ #undef _multiply_ #endif #define _multiply_(NAME) int ## _ ## NAME   #ifdef _multiply_type_ #undef _multiply_type_ #endif #define _multiply_type_ int   #include "multiply-template.h"  #endif 

int_multiply.c

#include "int_multiply.h" #include "multiply-template.c" 

At the end of all of this, you will have a function and header file for.

int int_multiply( int x, int y ) { return x * y } 

I created a much more detailed tutorial on the links provided. Hopefully this helps someone!

</div
 
 
3
 
vote

Подход, аналогичный принятым ответом, заключается в следующем:

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 7  

Этот файл заголовка должен пойти с помощью файла .c:

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 8  

При использовании функций

 <код> // the FOOBAR macro is needed to avoid the // extern foobar variable declaration #define FOOBAR  #include "foobar.h" #include "foobar_text.h" #include "foobar_date.h"  // creation of the namespace global variable struct _foobar_namespace foobar = {     .text = {         .print = foobar_text__print     },     .date = {         .getDateString = foobar_date__getDateString     } }; 9  
 

An approach similar to the accepted answer is the following:

// inclusion guard #ifndef FOOBAR_H_ #define FOOBAR_H_  // long names void foobar_some_func(int); void foobar_other_func();  // qualified names #ifdef FOOBAR_SHORT_NAMES extern struct _foobar {      void (*some_func)(int);      void (*other_func)(); } foobar; #endif  #endif 

this header file shall come with a .c file:

#include "foobar.h" struct _foobar foobar = {     foobar_some_func;     foobar_other_func; }; 

when using the functions,

foobar.some_func(10); foobar.other_func(); 
</div
 
 
1
 
vote

Вы можете использовать помощник <код> #include "foobar.h" void main() { foobar.text.print("it works"); } 0 макрос:

 <код> #include "foobar.h"  void main() {     foobar.text.print("it works"); } 1  

Пробега через препроцессор дает вам:

 <код> #include "foobar.h"  void main() {     foobar.text.print("it works"); } 2  
 

You can use a helper #define macro:

#include <stdio.h>  #define ns(x) gargantua_ ## x  struct ns(stats) {     int size; };  int ns(get_size)(struct ns(stats) *st) {     return st->size; }  void ns(set_size)(struct ns(stats) *st, int sz) {     st->size = sz; }  int main(void) {     struct ns(stats) stats = {0};      ns(set_size)(&stats, 3);     printf("size=%d ", ns(get_size)(&stats));     return 0; } 

Running it through the preprocessor gives you:

struct gargantua_stats {     int size; };  int gargantua_get_size(struct gargantua_stats *st) {     return st->size; }  void gargantua_set_size(struct gargantua_stats *st, int sz) {     st->size = sz; }  int main(void) {     struct gargantua_stats stats = {0};      gargantua_set_size(&stats, 3);     printf("size=%d ", gargantua_get_size(&stats));     return 0; } 
</div
 
 
0
 
vote

Вот пример, который создает вышеуказанные подходы и сочетает в себе как для функциональных функций для функций функций, так и для создания Pseudo-Namespaces Pespace Pespace1 и имен2. Преимущество этого чрезмерной структуры, которая проводит функции, заключается в том, что подход к структуре-функциям требует стандартизированной структуры в нескольких псевдо- именных пространствах, и это не всегда возможно (либо вообще, либо без большого количества работ, которые, возможно, не улучшать код) или желательно.

Не уверены, что порядок расширения макроса может быть проблемой, но это работает на GCC и, по-видимому, минимизирует объем необходимых изменений кода при поддержании достойного (хотья от идеальной) читаемости.


Application.c:

 <код> #include <stdio.h> #include "header1.h" #include "header2.h"  /* use NAMESPACE1 and NAMESPACE2 macros to choose namespace */  int main() {   NAMESPACE1(mystruct) data1; // structure specific to this namespace   NAMESPACE2(mystruct) data2;     data1.n1 = '1';   data1.c  = 'a';   data2.n2 = '2';   data2.c  = 'a';    NAMESPACE1(print_struct)(&data1); // function specific to this namespace   NAMESPACE2(print_struct)(&data2);  }   

header1.h

 <код> /* the below block is unnecessary, but gets rid of some compiler warnings */ #ifdef NAMESPACE_REAL #undef NAMESPACE_REAL #endif  /* edit the below lines to change the three occurrences of NAMESPACE1 to the desired namespace */ #define NAMESPACE1(name) NAMESPACE1 ## _ ## name #define NAMESPACE_REAL(name) NAMESPACE1(name)   /* don't edit the next block */ #define TYPEDEF(name, ...) typedef struct NAMESPACE_REAL(name) { __VA_ARGS__ } NAMESPACE_REAL(name) #define STRUCT(name) struct NAMESPACE_REAL(name) #define FUNC(name) NAMESPACE_REAL(name)  /* normal header code, using FUNC and STRUCT macros */ #include <stdio.h>  TYPEDEF(mystruct,         char n1;         char c;         );  void FUNC(print_struct)(STRUCT(mystruct) *data);  /* don't edit the rest */ #undef TYPEDEF   

API1.c:

 <код> #include "header1.h"  /* normal code, using FUNC and STRUCT macros */ void FUNC(print_struct)(STRUCT(mystruct) *data) {   printf("this is the struct from namespace1: %c %c ", data->n1, data->c); }   /* don't edit the rest */ #undef STRUCT #undef FUNC #undef NAMESPACE #undef NAMESPACE_REAL   

Другой код в Header2.h и API2.C такой же, как Header1.h и header2.h, модифицированный для пространства имен "nameespace2"

 

here is an example that builds off above approaches and combines them for both funcs and structures to create pseudo-namespaces NAMESPACE1 and NAMESPACE2. the benefit of this over having a structure that holds functions is that the structure-holding-functions approach requires a standardized structure across multiple pseudo-namespaces, and this is not always possible (either at all, or without a lot of work that arguably does not improve the code) or desirable.

Not sure if the macro expansion order could be an issue but this works on GCC and seems to minimize the amount of code changes required, while maintaining decent (though far from ideal) readability.


application.c:

#include <stdio.h> #include "header1.h" #include "header2.h"  /* use NAMESPACE1 and NAMESPACE2 macros to choose namespace */  int main() {   NAMESPACE1(mystruct) data1; // structure specific to this namespace   NAMESPACE2(mystruct) data2;     data1.n1 = '1';   data1.c  = 'a';   data2.n2 = '2';   data2.c  = 'a';    NAMESPACE1(print_struct)(&data1); // function specific to this namespace   NAMESPACE2(print_struct)(&data2);  } 

header1.h

/* the below block is unnecessary, but gets rid of some compiler warnings */ #ifdef NAMESPACE_REAL #undef NAMESPACE_REAL #endif  /* edit the below lines to change the three occurrences of NAMESPACE1 to the desired namespace */ #define NAMESPACE1(name) NAMESPACE1 ## _ ## name #define NAMESPACE_REAL(name) NAMESPACE1(name)   /* don't edit the next block */ #define TYPEDEF(name, ...) typedef struct NAMESPACE_REAL(name) { __VA_ARGS__ } NAMESPACE_REAL(name) #define STRUCT(name) struct NAMESPACE_REAL(name) #define FUNC(name) NAMESPACE_REAL(name)  /* normal header code, using FUNC and STRUCT macros */ #include <stdio.h>  TYPEDEF(mystruct,         char n1;         char c;         );  void FUNC(print_struct)(STRUCT(mystruct) *data);  /* don't edit the rest */ #undef TYPEDEF 

api1.c:

#include "header1.h"  /* normal code, using FUNC and STRUCT macros */ void FUNC(print_struct)(STRUCT(mystruct) *data) {   printf("this is the struct from namespace1: %c %c ", data->n1, data->c); }   /* don't edit the rest */ #undef STRUCT #undef FUNC #undef NAMESPACE #undef NAMESPACE_REAL 

Other code in header2.h and api2.c is the same as header1.h and header2.h, modified for namespace "NAMESPACE2"

</div
 
 
0
 
vote

Я понимаю, что это старый вопрос (11 лет), но я пытался по сути, по сути, что я думаю, вы хотели первоначально, как вы перечислены выше.

Я хотел, чтобы там было предпринимаемое пространство имен в моих функциях. Но я хотел, чтобы способность изменить то, что будет такое пространство имен. По умолчанию я хотел, чтобы этот пример не имел пространства имен, но если произошел столкновение именования, то я хотел, чтобы способность добавить пространство имен на все функции в моей библиотеке. (Это немного назад по сравнению с C ++, где по умолчанию есть пространство имен, и вы используете using namespace whatever , чтобы удалить необходимость указать пространство имен каждый раз.) Однако так же, как C ++, если вы бросаете <код > using namespace Заявление и псевдоним Ваш код, вам нужно будет обновить свой вызов. Вы можете написать какую-то другую последовательность макроса, чтобы автоматически переименовать ваши звонки, но это за пределами объема того, что я думаю, вы искали.

 <код> #include <stdio.h>  #define NAMESPACE(...) test_ //Use this as my prepender  //Where all the magic happens which could be included in a header file. #ifndef NAMESPACE //No Namespace by default #define NAMESPACE(...) #endif  //Actual replacements #define NSPREPENDER(...) NSPROCESSING(NAMESPACE(), __VA_ARGS__) #define NSPROCESSING(...) NSFINALIZE(__VA_ARGS__) #define NSFINALIZE(a,b) a ## b   //BEGIN ACTUAL PROGRAM //Prototype void NSPREPENDER(myprint)();  int main() {     test_myprint(); //If NAMESPACE(...) is defined to anything else, this code must change.      return 0; }  //Implementation void NSPREPENDER(myprint)() {     puts("Testing"); }   

Этот код будет компилировать только на C99 и выше, поскольку он использует вариационные макросы. Эти макросы делают форму рекурсии, которая все сделана, чтобы мы могли схватить значение из макроса, определенного в верхней части.

Разбивка всех работает:

    .
  • мы определяем, что мы хотим, чтобы наше пространство имен.
  • Если ничего не определено Установите по умолчанию
  • Сделайте кучу вызовов на обход и (ab), используют функциональность препроцессора.
  • добавьте функцию макроса NSPrepender к каждой функции C так, чтобы она могла быть именем.
  • Запишите код, используя Mangled Names, поскольку имя будет должным образом повреждено, когда компилятор увидит его.

Этот код был протестирован с clang.

 

I realize that this is an old question (11 years old), but I was trying to accomplish essentially what I think you wanted originally as you have listed above.

I wanted there to be a namespace prepended to my functions. But I wanted the ability to change what that namespace would be. By default I wanted for this example to not have a namespace, but if a naming collision occurred then I wanted the ability to prepend a namespace to all of the functions in my library. (This is slightly backwards compared to C++ where there is a namespace by default and you use using namespace whatever to remove the need to specify the namespace every time.) However, just like C++ if you drop in a using namespace statement and alias your code, you will need to update your calling code. You could write some other macro sequence to auto rename your calls as well, but that is outside the scope of what I think you were looking for.

#include <stdio.h>  #define NAMESPACE(...) test_ //Use this as my prepender  //Where all the magic happens which could be included in a header file. #ifndef NAMESPACE //No Namespace by default #define NAMESPACE(...) #endif  //Actual replacements #define NSPREPENDER(...) NSPROCESSING(NAMESPACE(), __VA_ARGS__) #define NSPROCESSING(...) NSFINALIZE(__VA_ARGS__) #define NSFINALIZE(a,b) a ## b   //BEGIN ACTUAL PROGRAM //Prototype void NSPREPENDER(myprint)();  int main() {     test_myprint(); //If NAMESPACE(...) is defined to anything else, this code must change.      return 0; }  //Implementation void NSPREPENDER(myprint)() {     puts("Testing"); } 

This code will compile only on C99 and up since it is using variadic macros. These macros do a form of recursion which is all done so that we can grab the value out of a macro defined at the top.

Breakdown of all it works:

  • We define that we want our namespace to be.
  • If nothing is defined set a default
  • Do a bunch of calls to bypass and (ab)use preprocessor functionality.
  • Add the NSPREPENDER macro function to each c function so that it can be name mangled.
  • Write code using mangled names since the name will be properly mangled by the time the compiler see it.

This code was tested with clang.

</div
 
 

Связанный проблема

10  Как я могу обнаружить доступ к файлу в Linux?  ( How can i detect file accesses in linux ) 
У меня есть куча потоков и приложений для обработки данных, которые я иногда нужно шпионить, то есть мне нужно знать, какие файлы они читают. Это в основном, ...

0  Как скопировать файлы из установленного местоположения в изолированное хранение в Windows Phone 8  ( How to copy files from installed location to isolated storage in windows phone 8 ) 
Я разрабатываю приложение для WP8 с помощью Cocos2DX. Я не могу найти функцию копирования, которая помогает мне копировать файлы с установленного местоположен...

145  Как определить, является ли строка номер с C ++?  ( How to determine if a string is a number with c ) 
У меня было довольно неприятностей, пытаясь написать функцию, которая проверяет, является ли строка номер. Для игры, которую я пишу, мне просто нужно проверит...

-2  Как писать сортировать с неизвестным аргументом. Не может повторяться с void * /  ( How write sort with unknown argument cant iterate with void ) 
в этом <код> void* ic = b + j * sz; и это <код> void* jc = ic - sz; lines IDE, написание того, что выражение должно быть указателем на полный тип. Мне нужен...

7  Как очистить удаленные объекты в C ++  ( How do clean up deleted objects in c ) 
Возможно ли использовать память об удаленных объектах в C ++? Я хочу сделать это, чтобы воспроизвести Coredump в модульном тесте: <код> //Some member variab...

1  Проблема с использованием TextureView с NDK  ( Issue using textureview with ndk ) 
Я работаю над небольшим кусочком кода, используя текстуру, чтобы отобразить результат среды MediaPlayer. Я сталкиваюсь с проблемой, пытающимся смешивать упр...

42  Как я могу легко увидеть график C / C ++ #include? [закрыто]  ( How can i see the c c include graph easily ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт. Этот вопрос не соответствует Рекомендациям переполнения ...

-1  Qt показывает изображение на 1/4 секунды  ( Qt show an image for 1 4 of a second ) 
Эй, я пробовал несколько раз, чтобы завершить это, используя Uslep или Qt Sleep, когда показывает изображение, но иногда (почти каждый раз) он появляется белы...

4  Строка :: Новая: что это?  ( Stringnew what is it ) 
Я из фона Java и изучает C ++. Я столкнулся с следующим C ++: <код> String source = String::New("'Hello' + ', World'"); Как то, что я так понимаю, это ...

7  Используйте простой класс C ++ в Android NDK  ( Use a simple c class in android ndk ) 
Я пытаюсь узнать основные основы Android NDK, но я застрял, когда я должен использовать его с классом C ++. Я понимаю, как использовать его с помощью просто...

3  Преобразование IPlimage в вектор в 1D в OpenCV  ( Converting iplimage into 1d vector in opencv ) 
Я хочу преобразовать MXN IPLIMAGE в вектору A (M * N) x 1 1. Может ли это сделать с любой функцией в OpenCV? Любая помощь значительно ценится. ...

29  C ++ Указатель на объекты  ( C pointer to objects ) 
в C ++ У вас всегда инициализировать указатель на объект с new ключевое слово? или вы просто имеете это тоже: <код> MyClass *myclass; myclass->DoSometh...

0  Использование Pybind11 на MacBook Pro  ( Using pybind11 on macbook pro ) 
Я пытаюсь использовать Pybind11 на MacBook, и я пытаюсь сделать так, как было написано в https://pybind11.readtheDocs.io/en/stable/basics.html я установил C...

-1  C ++ с использованием класса от заголовка в классе  ( C using a class from a header within a class ) 
У меня есть немного проблемы с классами, используемыми в классах, из файлов заголовка. У меня есть время занятий во времени. Как: <код> #ifndef TIME_H #de...

-2  Конструкторы ведут себя странным с кодом обработки исключений  ( Constructors behaving strange with exception handling code ) 
Скриншот # 1: Образец (образец & amp;) {...) // Нет ошибки без использования "const" Скриншот № 2: Destructor называется дважды, когда Copy-Constructor не вк...




© 2021 www.qaru.top All Rights Reserved. Q&A House все права защищены


Licensed under cc by-sa 3.0 with attribution required.