LINUX.ORG.RU

История изменений

Исправление Eddy_Em, (текущая версия) :

Получилось так (весь код теперь в заголовочном файле, а в сишном — только общее):

#define Fn1(A,B) A(x1)
#define Df1(A,B) A(B x1)
#define Fn2(A,B,C) A(x1, x2)
#define Df2(A,B,C) A(B x1, C x2)
#define Fn3(A,B,C,D) A(x1, x2, x3)
#define Df3(A,B,C,D) A(B x1, C x2, D x3)
#define Fn4(A,B,C,D,E) A(x1, x2, x3, x4)
#define Df4(A,B,C,D,E) A(B x1, C x2, D x3, E x4)
#define Fn5(A,B,C,D,E,F) A(x1, x2, x3, x4, x5)
#define Df5(A,B,C,D,E,F) A(B x1, C x2, D x3, E x4, F x5)
#define Fn6(A,B,C,D,E,F,G) A(x1, x2, x3, x4, x5, x6)
#define Df6(A,B,C,D,E,F,G) A(B x1, C x2, D x3, E x4, F x5, G x6)
#define Fn7(A,B,C,D,E,F,G,H) A(x1, x2, x3, x4, x5, x6, x7)
#define Df7(A,B,C,D,E,F,G,H) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7)
#define Fn8(A,B,C,D,E,F,G,H,I) A(x1, x2, x3, x4, x5, x6, x7, x8)
#define Df8(A,B,C,D,E,F,G,H,I) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8)
#define Fn9(A,B,C,D,E,F,G,H,I,J) A(x1, x2, x3, x4, x5, x6, x7, x8, x9)
#define Df9(A,B,C,D,E,F,G,H,I,J) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9)
#define Fn10(A,B,C,D,E,F,G,H,I,J,K) A(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)
#define Df10(A,B,C,D,E,F,G,H,I,J,K) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9, K x10)

#define DEF(N, ...) int Df ## N(__VA_ARGS__)
#define CONCAT(A, B) A ## B
#define FN(N, ...) Fn ## N(__VA_ARGS__)
#define DF(N, ...) Df ## N(__VA_ARGS__)
#define XFUNC(T, X) CONCAT(T, X)
#define FUNC(T, ...) XFUNC(T, FN(__VA_ARGS__))
#define DFUNC(T,...) EXTERN int XFUNC(T, DF(__VA_ARGS__))

#ifdef WRAPPER_C
// even when using cuda in case of fail CUDA init use CPU
static int Only_CPU =
#ifdef CUDA_FOUND
	0
#else
	1
#endif
;
#ifdef CUDA_FOUND
#define SET_F(...) DEF(__VA_ARGS__){					\
	if(!Only_CPU) if(FUNC(CU, __VA_ARGS__)) return 1;	\
	if(FUNC(CPU, __VA_ARGS__)) return 1;				\
	return 0;											\
}
#else
#define SET_F(...) DEF(__VA_ARGS__){					\
	if(FUNC(CPU, __VA_ARGS__)) return 1;				\
	return 0;											\
}
#endif // CUDA_FOUND
#else
	#define SET_F(...)
#endif // WRAPPER_C

#ifdef CPU_C // file included from CPU.c
	#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
	//#pragma message "CPUC"
#elif defined CUDA_CU //file included from CUDA.cu
	#define BOTH(...) DFUNC(CU, __VA_ARGS__);
#elif defined WRAPPER_C // wrapper.c needs names of both wariants
	#ifndef CUDA_FOUND
		#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
	#else
		#define BOTH(...) DFUNC(CU, __VA_ARGS__); DFUNC(CPU, __VA_ARGS__);
	#endif // CUDA_FOUND
#else // file included from something else - just define a function
	#define BOTH(...) DFUNC(, __VA_ARGS__);
#endif

#define DFN(...) BOTH(__VA_ARGS__) SET_F(__VA_ARGS__)


DFN(2, fillrandarr, size_t, float *)

DFN(6, bicubic_interp, float *, float *, size_t, size_t, size_t, size_t)

Макрос DFN объявляет (и определяет, если заголовочный файл включен из wrapper.c) функцию (второй аргумент макроса) с количеством аргументов, равным первому аргументу макроса и типами аргументов — остальными аргументами макроса. P.S. Если надо больше 10 аргументов — дописать соответствующие макросы DfXXX и FnXXX

Исходная версия Eddy_Em, :

Упростил-таки! На сосфорже натолкнули на хорошую идею.

Получилось так (весь код теперь в заголовочном файле, а в сишном — только общее):

#define Fn1(A,B) A(x1)
#define Df1(A,B) A(B x1)
#define Fn2(A,B,C) A(x1, x2)
#define Df2(A,B,C) A(B x1, C x2)
#define Fn3(A,B,C,D) A(x1, x2, x3)
#define Df3(A,B,C,D) A(B x1, C x2, D x3)
#define Fn4(A,B,C,D,E) A(x1, x2, x3, x4)
#define Df4(A,B,C,D,E) A(B x1, C x2, D x3, E x4)
#define Fn5(A,B,C,D,E,F) A(x1, x2, x3, x4, x5)
#define Df5(A,B,C,D,E,F) A(B x1, C x2, D x3, E x4, F x5)
#define Fn6(A,B,C,D,E,F,G) A(x1, x2, x3, x4, x5, x6)
#define Df6(A,B,C,D,E,F,G) A(B x1, C x2, D x3, E x4, F x5, G x6)
#define Fn7(A,B,C,D,E,F,G,H) A(x1, x2, x3, x4, x5, x6, x7)
#define Df7(A,B,C,D,E,F,G,H) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7)
#define Fn8(A,B,C,D,E,F,G,H,I) A(x1, x2, x3, x4, x5, x6, x7, x8)
#define Df8(A,B,C,D,E,F,G,H,I) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8)
#define Fn9(A,B,C,D,E,F,G,H,I,J) A(x1, x2, x3, x4, x5, x6, x7, x8, x9)
#define Df9(A,B,C,D,E,F,G,H,I,J) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9)
#define Fn10(A,B,C,D,E,F,G,H,I,J,K) A(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)
#define Df10(A,B,C,D,E,F,G,H,I,J,K) A(B x1, C x2, D x3, E x4, F x5, G x6, H x7, I x8, J x9, K x10)

#define DEF(N, ...) int Df ## N(__VA_ARGS__)
#define CONCAT(A, B) A ## B
#define FN(N, ...) Fn ## N(__VA_ARGS__)
#define DF(N, ...) Df ## N(__VA_ARGS__)
#define XFUNC(T, X) CONCAT(T, X)
#define FUNC(T, ...) XFUNC(T, FN(__VA_ARGS__))
#define DFUNC(T,...) EXTERN int XFUNC(T, DF(__VA_ARGS__))

#ifdef WRAPPER_C
// even when using cuda in case of fail CUDA init use CPU
static int Only_CPU =
#ifdef CUDA_FOUND
	0
#else
	1
#endif
;
#ifdef CUDA_FOUND
#define SET_F(...) DEF(__VA_ARGS__){					\
	if(!Only_CPU) if(FUNC(CU, __VA_ARGS__)) return 1;	\
	if(FUNC(CPU, __VA_ARGS__)) return 1;				\
	return 0;											\
}
#else
#define SET_F(...) DEF(__VA_ARGS__){					\
	if(FUNC(CPU, __VA_ARGS__)) return 1;				\
	return 0;											\
}
#endif // CUDA_FOUND
#else
	#define SET_F(...)
#endif // WRAPPER_C

#ifdef CPU_C // file included from CPU.c
	#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
	//#pragma message "CPUC"
#elif defined CUDA_CU //file included from CUDA.cu
	#define BOTH(...) DFUNC(CU, __VA_ARGS__);
#elif defined WRAPPER_C // wrapper.c needs names of both wariants
	#ifndef CUDA_FOUND
		#define BOTH(...) DFUNC(CPU, __VA_ARGS__);
	#else
		#define BOTH(...) DFUNC(CU, __VA_ARGS__); DFUNC(CPU, __VA_ARGS__);
	#endif // CUDA_FOUND
#else // file included from something else - just define a function
	#define BOTH(...) DFUNC(, __VA_ARGS__);
#endif

#define DFN(...) BOTH(__VA_ARGS__) SET_F(__VA_ARGS__)


DFN(2, fillrandarr, size_t, float *)

DFN(6, bicubic_interp, float *, float *, size_t, size_t, size_t, size_t)

Макрос DFN объявляет (и определяет, если заголовочный файл включен из wrapper.c) функцию (второй аргумент макроса) с количеством аргументов, равным первому аргументу макроса и типами аргументов — остальными аргументами макроса.