diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py
index 832ede696f92b054c1b3d15a5218cffef7fcc6fc..b61409f014c55edb1c6a9358650ac2ed5649374b 100644
--- a/pyopencl/cffi_cl.py
+++ b/pyopencl/cffi_cl.py
@@ -140,22 +140,19 @@ def get_cl_header_version():
         
 _CL_VERSION = get_cl_header_version()
 
-_constants = PP(_ffi.new('constant**'))
-_lib.get_constants(_constants.ptr, _constants.size)
-
-def _create_constants_class(name):
-    return type(name, (NoInit,), dict((_ffi.string(c.name), c.value) for c in _constants if _ffi.string(c.type) == name))
-
-platform_info = _create_constants_class("platform_info")
-device_type = _create_constants_class("device_type")
-device_info = _create_constants_class("device_info")
-mem_flags = _create_constants_class("mem_flags")
-mem_info = _create_constants_class("mem_info")
-mem_object_type = _create_constants_class("mem_object_type")
-program_info = _create_constants_class("program_info")
-program_build_info = _create_constants_class("program_build_info")
-program_binary_type = _create_constants_class("program_binary_type")
-kernel_info = _create_constants_class("kernel_info")
+# {{{ expose constants classes like platform_info, device_type, ...
+_constants = {}
+@_ffi.callback('void(const char*, const char* name, unsigned int value)')
+def _constant_callback(type_, name, value):
+    s_type = _ffi.string(type_)
+    _constants.setdefault(s_type, {})
+    _constants[s_type][_ffi.string(name)] = value
+_lib.populate_constants(_constant_callback)
+
+for type_, d in _constants.iteritems():
+    locals()[type_] = type(type_, (NoInit,), d)
+# }}}
+
 class EQUALITY_TESTS(object):
     def __eq__(self, other):
         return hash(self) == hash(other)
diff --git a/src/c_wrapper/Makefile b/src/c_wrapper/Makefile
index 7114b1a32b682e2c1259e711f96405c98cada9ce..2e1cc6d78fbba79480aec1dbf50bc415bdfb5f16 100644
--- a/src/c_wrapper/Makefile
+++ b/src/c_wrapper/Makefile
@@ -1,5 +1,5 @@
 all:
-	g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -Werror -fpic wrap_cl.c
-	g++ -shared -o libwrapcl.so wrap_cl.o
+	g++ -c -Wall -DPYOPENCL_PRETEND_CL_VERSION=4112 -Werror -fpic wrap_cl.cpp wrap_constants.cpp
+	g++ -shared -o libwrapcl.so wrap_cl.o wrap_constants.o
 	cp libwrapcl.so ../../pyopencl/
 	cp wrap_cl_core.h ../../pyopencl/wrap_cl_core.h
diff --git a/src/c_wrapper/wrap_cl.c b/src/c_wrapper/wrap_cl.cpp
similarity index 92%
rename from src/c_wrapper/wrap_cl.c
rename to src/c_wrapper/wrap_cl.cpp
index 9e43458f3e5aabbe2c59b661886710b7a3be84ba..dc17f999c2cf11b93c775a786fb4a4937c64e5d4 100644
--- a/src/c_wrapper/wrap_cl.c
+++ b/src/c_wrapper/wrap_cl.cpp
@@ -2148,7 +2148,8 @@ inline event *enqueue_nd_range_kernel(
     return 0;
   }
 
-  void get_constants(constant** out, uint32_t *num_constants) {
+  void get_constants(constant** out, uint32_t *num_constants, void(*callback)(const char*)) {
+    callback("hallo");
 #define ADD_ATTR(TYPE, PREFIX, NAME)					\
     constants.push_back((constant){TYPE, #NAME, CL_##PREFIX##NAME});
     
@@ -2173,154 +2174,154 @@ inline event *enqueue_nd_range_kernel(
 #endif
     ADD_ATTR("device_type", DEVICE_TYPE_, ALL);
     
-    // DEVICE
-    ADD_ATTR("device_type", DEVICE_, TYPE);
-    ADD_ATTR("device_type", DEVICE_, VENDOR_ID);
-    ADD_ATTR("device_type", DEVICE_, MAX_COMPUTE_UNITS);
-    ADD_ATTR("device_type", DEVICE_, MAX_WORK_ITEM_DIMENSIONS);
-    ADD_ATTR("device_type", DEVICE_, MAX_WORK_GROUP_SIZE);
-    ADD_ATTR("device_type", DEVICE_, MAX_WORK_ITEM_SIZES);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_CHAR);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_SHORT);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_INT);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_LONG);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_FLOAT);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_DOUBLE);
-    ADD_ATTR("device_type", DEVICE_, MAX_CLOCK_FREQUENCY);
-    ADD_ATTR("device_type", DEVICE_, ADDRESS_BITS);
-    ADD_ATTR("device_type", DEVICE_, MAX_READ_IMAGE_ARGS);
-    ADD_ATTR("device_type", DEVICE_, MAX_WRITE_IMAGE_ARGS);
-    ADD_ATTR("device_type", DEVICE_, MAX_MEM_ALLOC_SIZE);
-    ADD_ATTR("device_type", DEVICE_, IMAGE2D_MAX_WIDTH);
-    ADD_ATTR("device_type", DEVICE_, IMAGE2D_MAX_HEIGHT);
-    ADD_ATTR("device_type", DEVICE_, IMAGE3D_MAX_WIDTH);
-    ADD_ATTR("device_type", DEVICE_, IMAGE3D_MAX_HEIGHT);
-    ADD_ATTR("device_type", DEVICE_, IMAGE3D_MAX_DEPTH);
-    ADD_ATTR("device_type", DEVICE_, IMAGE_SUPPORT);
-    ADD_ATTR("device_type", DEVICE_, MAX_PARAMETER_SIZE);
-    ADD_ATTR("device_type", DEVICE_, MAX_SAMPLERS);
-    ADD_ATTR("device_type", DEVICE_, MEM_BASE_ADDR_ALIGN);
-    ADD_ATTR("device_type", DEVICE_, MIN_DATA_TYPE_ALIGN_SIZE);
-    ADD_ATTR("device_type", DEVICE_, SINGLE_FP_CONFIG);
+    // DEVICE_INFO
+    ADD_ATTR("device_info", DEVICE_, TYPE);
+    ADD_ATTR("device_info", DEVICE_, VENDOR_ID);
+    ADD_ATTR("device_info", DEVICE_, MAX_COMPUTE_UNITS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_ITEM_DIMENSIONS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_GROUP_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_ITEM_SIZES);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_CHAR);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_SHORT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_INT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_LONG);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_FLOAT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_DOUBLE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CLOCK_FREQUENCY);
+    ADD_ATTR("device_info", DEVICE_, ADDRESS_BITS);
+    ADD_ATTR("device_info", DEVICE_, MAX_READ_IMAGE_ARGS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WRITE_IMAGE_ARGS);
+    ADD_ATTR("device_info", DEVICE_, MAX_MEM_ALLOC_SIZE);
+    ADD_ATTR("device_info", DEVICE_, IMAGE2D_MAX_WIDTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE2D_MAX_HEIGHT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_WIDTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_HEIGHT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_DEPTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_SUPPORT);
+    ADD_ATTR("device_info", DEVICE_, MAX_PARAMETER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_SAMPLERS);
+    ADD_ATTR("device_info", DEVICE_, MEM_BASE_ADDR_ALIGN);
+    ADD_ATTR("device_info", DEVICE_, MIN_DATA_TYPE_ALIGN_SIZE);
+    ADD_ATTR("device_info", DEVICE_, SINGLE_FP_CONFIG);
 #ifdef CL_DEVICEDOUBLE_FP_CONFIG
-    ADD_ATTR("device_type", DEVICE_, DOUBLE_FP_CONFIG);
+    ADD_ATTR("device_info", DEVICE_, DOUBLE_FP_CONFIG);
 #endif
 #ifdef CL_DEVICEHALF_FP_CONFIG
-    ADD_ATTR("device_type", DEVICE_, HALF_FP_CONFIG);
+    ADD_ATTR("device_info", DEVICE_, HALF_FP_CONFIG);
 #endif
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CACHE_TYPE);
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CACHELINE_SIZE);
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CACHE_SIZE);
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_SIZE);
-    ADD_ATTR("device_type", DEVICE_, MAX_CONSTANT_BUFFER_SIZE);
-    ADD_ATTR("device_type", DEVICE_, MAX_CONSTANT_ARGS);
-    ADD_ATTR("device_type", DEVICE_, LOCAL_MEM_TYPE);
-    ADD_ATTR("device_type", DEVICE_, LOCAL_MEM_SIZE);
-    ADD_ATTR("device_type", DEVICE_, ERROR_CORRECTION_SUPPORT);
-    ADD_ATTR("device_type", DEVICE_, PROFILING_TIMER_RESOLUTION);
-    ADD_ATTR("device_type", DEVICE_, ENDIAN_LITTLE);
-    ADD_ATTR("device_type", DEVICE_, AVAILABLE);
-    ADD_ATTR("device_type", DEVICE_, COMPILER_AVAILABLE);
-    ADD_ATTR("device_type", DEVICE_, EXECUTION_CAPABILITIES);
-    ADD_ATTR("device_type", DEVICE_, QUEUE_PROPERTIES);
-    ADD_ATTR("device_type", DEVICE_, NAME);
-    ADD_ATTR("device_type", DEVICE_, VENDOR);
-    ADD_ATTR("device_type", , DRIVER_VERSION);
-    ADD_ATTR("device_type", DEVICE_, VERSION);
-    ADD_ATTR("device_type", DEVICE_, PROFILE);
-    ADD_ATTR("device_type", DEVICE_, VERSION);
-    ADD_ATTR("device_type", DEVICE_, EXTENSIONS);
-    ADD_ATTR("device_type", DEVICE_, PLATFORM);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHE_TYPE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHELINE_SIZE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHE_SIZE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CONSTANT_BUFFER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CONSTANT_ARGS);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_TYPE);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_SIZE);
+    ADD_ATTR("device_info", DEVICE_, ERROR_CORRECTION_SUPPORT);
+    ADD_ATTR("device_info", DEVICE_, PROFILING_TIMER_RESOLUTION);
+    ADD_ATTR("device_info", DEVICE_, ENDIAN_LITTLE);
+    ADD_ATTR("device_info", DEVICE_, AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, COMPILER_AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, EXECUTION_CAPABILITIES);
+    ADD_ATTR("device_info", DEVICE_, QUEUE_PROPERTIES);
+    ADD_ATTR("device_info", DEVICE_, NAME);
+    ADD_ATTR("device_info", DEVICE_, VENDOR);
+    ADD_ATTR("device_info", , DRIVER_VERSION);
+    ADD_ATTR("device_info", DEVICE_, VERSION);
+    ADD_ATTR("device_info", DEVICE_, PROFILE);
+    ADD_ATTR("device_info", DEVICE_, VERSION);
+    ADD_ATTR("device_info", DEVICE_, EXTENSIONS);
+    ADD_ATTR("device_info", DEVICE_, PLATFORM);
 #if PYOPENCL_CL_VERSION >= 0x1010
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_VECTOR_WIDTH_HALF);
-    ADD_ATTR("device_type", DEVICE_, HOST_UNIFIED_MEMORY);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_CHAR);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_SHORT);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_INT);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_LONG);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_FLOAT);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_DOUBLE);
-    ADD_ATTR("device_type", DEVICE_, NATIVE_VECTOR_WIDTH_HALF);
-    ADD_ATTR("device_type", DEVICE_, OPENCL_C_VERSION);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_HALF);
+    ADD_ATTR("device_info", DEVICE_, HOST_UNIFIED_MEMORY);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_CHAR);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_SHORT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_INT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_LONG);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_FLOAT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_DOUBLE);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_HALF);
+    ADD_ATTR("device_info", DEVICE_, OPENCL_C_VERSION);
 #endif
     // support for cl_nv_DEVICEattribute_query
 #ifdef CL_DEVICECOMPUTE_CAPABILITY_MAJOR_NV
-    ADD_ATTR("device_type", DEVICE_, COMPUTE_CAPABILITY_MAJOR_NV);
-    ADD_ATTR("device_type", DEVICE_, COMPUTE_CAPABILITY_MINOR_NV);
-    ADD_ATTR("device_type", DEVICE_, REGISTERS_PER_BLOCK_NV);
-    ADD_ATTR("device_type", DEVICE_, WARP_SIZE_NV);
-    ADD_ATTR("device_type", DEVICE_, GPU_OVERLAP_NV);
-    ADD_ATTR("device_type", DEVICE_, KERNEL_EXEC_TIMEOUT_NV);
-    ADD_ATTR("device_type", DEVICE_, INTEGRATED_MEMORY_NV);
+    ADD_ATTR("device_info", DEVICE_, COMPUTE_CAPABILITY_MAJOR_NV);
+    ADD_ATTR("device_info", DEVICE_, COMPUTE_CAPABILITY_MINOR_NV);
+    ADD_ATTR("device_info", DEVICE_, REGISTERS_PER_BLOCK_NV);
+    ADD_ATTR("device_info", DEVICE_, WARP_SIZE_NV);
+    ADD_ATTR("device_info", DEVICE_, GPU_OVERLAP_NV);
+    ADD_ATTR("device_info", DEVICE_, KERNEL_EXEC_TIMEOUT_NV);
+    ADD_ATTR("device_info", DEVICE_, INTEGRATED_MEMORY_NV);
 #endif
     // {{{ cl_amd_DEVICEattribute_query
 #ifdef CL_DEVICEPROFILING_TIMER_OFFSET_AMD
-    ADD_ATTR("device_type", DEVICE_, PROFILING_TIMER_OFFSET_AMD);
+    ADD_ATTR("device_info", DEVICE_, PROFILING_TIMER_OFFSET_AMD);
 #endif
 #ifdef CL_DEVICETOPOLOGY_AMD
-    ADD_ATTR("device_type", DEVICE_, TOPOLOGY_AMD);
+    ADD_ATTR("device_info", DEVICE_, TOPOLOGY_AMD);
 #endif
 #ifdef CL_DEVICEBOARD_NAME_AMD
-    ADD_ATTR("device_type", DEVICE_, BOARD_NAME_AMD);
+    ADD_ATTR("device_info", DEVICE_, BOARD_NAME_AMD);
 #endif
 #ifdef CL_DEVICEGLOBAL_FREE_MEMORY_AMD
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_FREE_MEMORY_AMD);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_FREE_MEMORY_AMD);
 #endif
 #ifdef CL_DEVICESIMD_PER_COMPUTE_UNIT_AMD
-    ADD_ATTR("device_type", DEVICE_, SIMD_PER_COMPUTE_UNIT_AMD);
+    ADD_ATTR("device_info", DEVICE_, SIMD_PER_COMPUTE_UNIT_AMD);
 #endif
 #ifdef CL_DEVICESIMD_WIDTH_AMD
-    ADD_ATTR("device_type", DEVICE_, SIMD_WIDTH_AMD);
+    ADD_ATTR("device_info", DEVICE_, SIMD_WIDTH_AMD);
 #endif
 #ifdef CL_DEVICESIMD_INSTRUCTION_WIDTH_AMD
-    ADD_ATTR("device_type", DEVICE_, SIMD_INSTRUCTION_WIDTH_AMD);
+    ADD_ATTR("device_info", DEVICE_, SIMD_INSTRUCTION_WIDTH_AMD);
 #endif
 #ifdef CL_DEVICEWAVEFRONT_WIDTH_AMD
-    ADD_ATTR("device_type", DEVICE_, WAVEFRONT_WIDTH_AMD);
+    ADD_ATTR("device_info", DEVICE_, WAVEFRONT_WIDTH_AMD);
 #endif
 #ifdef CL_DEVICEGLOBAL_MEM_CHANNELS_AMD
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CHANNELS_AMD);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNELS_AMD);
 #endif
 #ifdef CL_DEVICEGLOBAL_MEM_CHANNEL_BANKS_AMD
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CHANNEL_BANKS_AMD);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNEL_BANKS_AMD);
 #endif
 #ifdef CL_DEVICEGLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
-    ADD_ATTR("device_type", DEVICE_, GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD);
 #endif
 #ifdef CL_DEVICELOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
-    ADD_ATTR("device_type", DEVICE_, LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD);
 #endif
 #ifdef CL_DEVICELOCAL_MEM_BANKS_AMD
-    ADD_ATTR("device_type", DEVICE_, LOCAL_MEM_BANKS_AMD);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_BANKS_AMD);
 #endif
     // }}}
 #ifdef CL_DEVICEMAX_ATOMIC_COUNTERS_EXT
-    ADD_ATTR("device_type", DEVICE_, MAX_ATOMIC_COUNTERS_EXT);
+    ADD_ATTR("device_info", DEVICE_, MAX_ATOMIC_COUNTERS_EXT);
 #endif
 #if defined(cl_ext_DEVICEfission) && defined(PYOPENCL_USE_DEVICEFISSION)
-    ADD_ATTR("device_type", DEVICE_, PARENT_DEVICEEXT);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_TYPES_EXT);
-    ADD_ATTR("device_type", DEVICE_, AFFINITY_DOMAINS_EXT);
-    ADD_ATTR("device_type", DEVICE_, REFERENCE_COUNT_EXT);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_STYLE_EXT);
+    ADD_ATTR("device_info", DEVICE_, PARENT_DEVICEEXT);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_TYPES_EXT);
+    ADD_ATTR("device_info", DEVICE_, AFFINITY_DOMAINS_EXT);
+    ADD_ATTR("device_info", DEVICE_, REFERENCE_COUNT_EXT);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_STYLE_EXT);
 #endif
 #if PYOPENCL_CL_VERSION >= 0x1020
-    ADD_ATTR("device_type", DEVICE_, LINKER_AVAILABLE);
-    ADD_ATTR("device_type", DEVICE_, BUILT_IN_KERNELS);
-    ADD_ATTR("device_type", DEVICE_, IMAGE_MAX_BUFFER_SIZE);
-    ADD_ATTR("device_type", DEVICE_, IMAGE_MAX_ARRAY_SIZE);
-    ADD_ATTR("device_type", DEVICE_, PARENT_DEVICE);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_MAX_SUB_DEVICES);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_PROPERTIES);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_AFFINITY_DOMAIN);
-    ADD_ATTR("device_type", DEVICE_, PARTITION_TYPE);
-    ADD_ATTR("device_type", DEVICE_, REFERENCE_COUNT);
-    ADD_ATTR("device_type", DEVICE_, PREFERRED_INTEROP_USER_SYNC);
-    ADD_ATTR("device_type", DEVICE_, PRINTF_BUFFER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, LINKER_AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, BUILT_IN_KERNELS);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_MAX_BUFFER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_MAX_ARRAY_SIZE);
+    ADD_ATTR("device_info", DEVICE_, PARENT_DEVICE);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_MAX_SUB_DEVICES);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_PROPERTIES);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_AFFINITY_DOMAIN);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_TYPE);
+    ADD_ATTR("device_info", DEVICE_, REFERENCE_COUNT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_INTEROP_USER_SYNC);
+    ADD_ATTR("device_info", DEVICE_, PRINTF_BUFFER_SIZE);
 #endif
 #ifdef cl_khr_image2d_from_buffer
-    ADD_ATTR("device_type", DEVICE_, IMAGE_PITCH_ALIGNMENT);
-    ADD_ATTR("device_type", DEVICE_, IMAGE_BASE_ADDRESS_ALIGNMENT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_PITCH_ALIGNMENT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_BASE_ADDRESS_ALIGNMENT);
 #endif
 
     // mem_flags
@@ -2409,6 +2410,7 @@ inline event *enqueue_nd_range_kernel(
     *out = c;
     *num_constants = constants.size();
   }
+
   
 }
 
diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h
index 30b42de52e4eb9c40f0954f3bf89fad6639967d0..9ee058cb5a620dc806a03c717fb1838afc9113fb 100644
--- a/src/c_wrapper/wrap_cl_core.h
+++ b/src/c_wrapper/wrap_cl_core.h
@@ -37,5 +37,15 @@ void* kernel__set_arg_mem_buffer(void* ptr_kernel, cl_uint arg_index, void* ptr_
 void* _enqueue_nd_range_kernel(void **ptr_event, void* ptr_command_queue, void* ptr_kernel, cl_uint work_dim, const size_t* global_work_offset, const size_t* global_work_size, const size_t* local_work_size);
 void* _enqueue_read_buffer(void **ptr_event, void* ptr_command_queue, void* ptr_memory_object_holder, void* buffer, size_t size, size_t device_offset, int is_blocking);
 void* memory_object_holder__get_info(void* ptr_memory_object_holder, cl_mem_info param, generic_info* out);
-void get_constants(constant** out, uint32_t *num_constants);
+void get_constants(constant** out, uint32_t *num_constants, void(*)(const char*));
+void populate_constants(void(*add)(const char*, const char*, unsigned int value));
 void freem(void*);
+
+
+
+
+
+
+
+
+
diff --git a/src/c_wrapper/wrap_constants.cpp b/src/c_wrapper/wrap_constants.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c4f0e1f77581fb62148868544bffdee054e93001
--- /dev/null
+++ b/src/c_wrapper/wrap_constants.cpp
@@ -0,0 +1,576 @@
+#include "wrap_cl.h"
+
+extern "C"
+namespace pyopencl {
+  void populate_constants(void(*add)(const char*, const char*, unsigned int value)) {
+#define ADD_ATTR(TYPE, PREFIX, NAME)		\
+    add(TYPE, #NAME, CL_##PREFIX##NAME)
+    
+    // status_code
+    ADD_ATTR("status_code", , SUCCESS);
+    ADD_ATTR("status_code", , DEVICE_NOT_FOUND);
+    ADD_ATTR("status_code", , DEVICE_NOT_AVAILABLE);
+#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
+    ADD_ATTR("status_code", , COMPILER_NOT_AVAILABLE);
+#endif
+    ADD_ATTR("status_code", , MEM_OBJECT_ALLOCATION_FAILURE);
+    ADD_ATTR("status_code", , OUT_OF_RESOURCES);
+    ADD_ATTR("status_code", , OUT_OF_HOST_MEMORY);
+    ADD_ATTR("status_code", , PROFILING_INFO_NOT_AVAILABLE);
+    ADD_ATTR("status_code", , MEM_COPY_OVERLAP);
+    ADD_ATTR("status_code", , IMAGE_FORMAT_MISMATCH);
+    ADD_ATTR("status_code", , IMAGE_FORMAT_NOT_SUPPORTED);
+    ADD_ATTR("status_code", , BUILD_PROGRAM_FAILURE);
+    ADD_ATTR("status_code", , MAP_FAILURE);
+    ADD_ATTR("status_code", , INVALID_VALUE);
+    ADD_ATTR("status_code", , INVALID_DEVICE_TYPE);
+    ADD_ATTR("status_code", , INVALID_PLATFORM);
+    ADD_ATTR("status_code", , INVALID_DEVICE);
+    ADD_ATTR("status_code", , INVALID_CONTEXT);
+    ADD_ATTR("status_code", , INVALID_QUEUE_PROPERTIES);
+    ADD_ATTR("status_code", , INVALID_COMMAND_QUEUE);
+    ADD_ATTR("status_code", , INVALID_HOST_PTR);
+    ADD_ATTR("status_code", , INVALID_MEM_OBJECT);
+    ADD_ATTR("status_code", , INVALID_IMAGE_FORMAT_DESCRIPTOR);
+    ADD_ATTR("status_code", , INVALID_IMAGE_SIZE);
+    ADD_ATTR("status_code", , INVALID_SAMPLER);
+    ADD_ATTR("status_code", , INVALID_BINARY);
+    ADD_ATTR("status_code", , INVALID_BUILD_OPTIONS);
+    ADD_ATTR("status_code", , INVALID_PROGRAM);
+    ADD_ATTR("status_code", , INVALID_PROGRAM_EXECUTABLE);
+    ADD_ATTR("status_code", , INVALID_KERNEL_NAME);
+    ADD_ATTR("status_code", , INVALID_KERNEL_DEFINITION);
+    ADD_ATTR("status_code", , INVALID_KERNEL);
+    ADD_ATTR("status_code", , INVALID_ARG_INDEX);
+    ADD_ATTR("status_code", , INVALID_ARG_VALUE);
+    ADD_ATTR("status_code", , INVALID_ARG_SIZE);
+    ADD_ATTR("status_code", , INVALID_KERNEL_ARGS);
+    ADD_ATTR("status_code", , INVALID_WORK_DIMENSION);
+    ADD_ATTR("status_code", , INVALID_WORK_GROUP_SIZE);
+    ADD_ATTR("status_code", , INVALID_WORK_ITEM_SIZE);
+    ADD_ATTR("status_code", , INVALID_GLOBAL_OFFSET);
+    ADD_ATTR("status_code", , INVALID_EVENT_WAIT_LIST);
+    ADD_ATTR("status_code", , INVALID_EVENT);
+    ADD_ATTR("status_code", , INVALID_OPERATION);
+    ADD_ATTR("status_code", , INVALID_GL_OBJECT);
+    ADD_ATTR("status_code", , INVALID_BUFFER_SIZE);
+    ADD_ATTR("status_code", , INVALID_MIP_LEVEL);
+#if defined(cl_khr_icd) && (cl_khr_icd >= 1)
+    ADD_ATTR("status_code", , PLATFORM_NOT_FOUND_KHR);
+#endif
+#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
+    ADD_ATTR("status_code", , INVALID_GL_SHAREGROUP_REFERENCE_KHR);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("status_code", , MISALIGNED_SUB_BUFFER_OFFSET);
+    ADD_ATTR("status_code", , EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
+    ADD_ATTR("status_code", , INVALID_GLOBAL_WORK_SIZE);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("status_code", , COMPILE_PROGRAM_FAILURE);
+    ADD_ATTR("status_code", , LINKER_NOT_AVAILABLE);
+    ADD_ATTR("status_code", , LINK_PROGRAM_FAILURE);
+    ADD_ATTR("status_code", , DEVICE_PARTITION_FAILED);
+    ADD_ATTR("status_code", , KERNEL_ARG_INFO_NOT_AVAILABLE);
+    ADD_ATTR("status_code", , INVALID_IMAGE_DESCRIPTOR);
+    ADD_ATTR("status_code", , INVALID_COMPILER_OPTIONS);
+    ADD_ATTR("status_code", , INVALID_LINKER_OPTIONS);
+    ADD_ATTR("status_code", , INVALID_DEVICE_PARTITION_COUNT);
+#endif
+#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
+    ADD_ATTR("status_code", , DEVICE_PARTITION_FAILED_EXT);
+    ADD_ATTR("status_code", , INVALID_PARTITION_COUNT_EXT);
+    ADD_ATTR("status_code", , INVALID_PARTITION_NAME_EXT);
+#endif
+    // platform_info
+    ADD_ATTR("platform_info", PLATFORM_, PROFILE);
+    ADD_ATTR("platform_info", PLATFORM_, VERSION);
+    ADD_ATTR("platform_info", PLATFORM_, NAME);
+    ADD_ATTR("platform_info", PLATFORM_, VENDOR);
+#if !(defined(CL_PLATFORM_NVIDIA) && CL_PLATFORM_NVIDIA == 0x3001)
+    ADD_ATTR("platform_info", PLATFORM_, EXTENSIONS);
+#endif
+    // device_type
+    ADD_ATTR("device_type", DEVICE_TYPE_, DEFAULT);
+    ADD_ATTR("device_type", DEVICE_TYPE_, CPU);
+    ADD_ATTR("device_type", DEVICE_TYPE_, GPU);
+    ADD_ATTR("device_type", DEVICE_TYPE_, ACCELERATOR);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("device_type", DEVICE_TYPE_, CUSTOM);
+#endif
+    ADD_ATTR("device_type", DEVICE_TYPE_, ALL);
+    // device_info
+    ADD_ATTR("device_info", DEVICE_, TYPE);
+    ADD_ATTR("device_info", DEVICE_, VENDOR_ID);
+    ADD_ATTR("device_info", DEVICE_, MAX_COMPUTE_UNITS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_ITEM_DIMENSIONS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_GROUP_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_WORK_ITEM_SIZES);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_CHAR);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_SHORT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_INT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_LONG);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_FLOAT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_DOUBLE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CLOCK_FREQUENCY);
+    ADD_ATTR("device_info", DEVICE_, ADDRESS_BITS);
+    ADD_ATTR("device_info", DEVICE_, MAX_READ_IMAGE_ARGS);
+    ADD_ATTR("device_info", DEVICE_, MAX_WRITE_IMAGE_ARGS);
+    ADD_ATTR("device_info", DEVICE_, MAX_MEM_ALLOC_SIZE);
+    ADD_ATTR("device_info", DEVICE_, IMAGE2D_MAX_WIDTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE2D_MAX_HEIGHT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_WIDTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_HEIGHT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE3D_MAX_DEPTH);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_SUPPORT);
+    ADD_ATTR("device_info", DEVICE_, MAX_PARAMETER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_SAMPLERS);
+    ADD_ATTR("device_info", DEVICE_, MEM_BASE_ADDR_ALIGN);
+    ADD_ATTR("device_info", DEVICE_, MIN_DATA_TYPE_ALIGN_SIZE);
+    ADD_ATTR("device_info", DEVICE_, SINGLE_FP_CONFIG);
+#ifdef CL_DEVICE_DOUBLE_FP_CONFIG
+    ADD_ATTR("device_info", DEVICE_, DOUBLE_FP_CONFIG);
+#endif
+#ifdef CL_DEVICE_HALF_FP_CONFIG
+    ADD_ATTR("device_info", DEVICE_, HALF_FP_CONFIG);
+#endif
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHE_TYPE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHELINE_SIZE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CACHE_SIZE);
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CONSTANT_BUFFER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, MAX_CONSTANT_ARGS);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_TYPE);
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_SIZE);
+    ADD_ATTR("device_info", DEVICE_, ERROR_CORRECTION_SUPPORT);
+    ADD_ATTR("device_info", DEVICE_, PROFILING_TIMER_RESOLUTION);
+    ADD_ATTR("device_info", DEVICE_, ENDIAN_LITTLE);
+    ADD_ATTR("device_info", DEVICE_, AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, COMPILER_AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, EXECUTION_CAPABILITIES);
+    ADD_ATTR("device_info", DEVICE_, QUEUE_PROPERTIES);
+    ADD_ATTR("device_info", DEVICE_, NAME);
+    ADD_ATTR("device_info", DEVICE_, VENDOR);
+    ADD_ATTR("device_info", , DRIVER_VERSION);
+    ADD_ATTR("device_info", DEVICE_, VERSION);
+    ADD_ATTR("device_info", DEVICE_, PROFILE);
+    ADD_ATTR("device_info", DEVICE_, VERSION);
+    ADD_ATTR("device_info", DEVICE_, EXTENSIONS);
+    ADD_ATTR("device_info", DEVICE_, PLATFORM);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_VECTOR_WIDTH_HALF);
+    ADD_ATTR("device_info", DEVICE_, HOST_UNIFIED_MEMORY);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_CHAR);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_SHORT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_INT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_LONG);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_FLOAT);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_DOUBLE);
+    ADD_ATTR("device_info", DEVICE_, NATIVE_VECTOR_WIDTH_HALF);
+    ADD_ATTR("device_info", DEVICE_, OPENCL_C_VERSION);
+#endif
+#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
+    ADD_ATTR("device_info", DEVICE_, COMPUTE_CAPABILITY_MAJOR_NV);
+    ADD_ATTR("device_info", DEVICE_, COMPUTE_CAPABILITY_MINOR_NV);
+    ADD_ATTR("device_info", DEVICE_, REGISTERS_PER_BLOCK_NV);
+    ADD_ATTR("device_info", DEVICE_, WARP_SIZE_NV);
+    ADD_ATTR("device_info", DEVICE_, GPU_OVERLAP_NV);
+    ADD_ATTR("device_info", DEVICE_, KERNEL_EXEC_TIMEOUT_NV);
+    ADD_ATTR("device_info", DEVICE_, INTEGRATED_MEMORY_NV);
+#endif
+#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
+    ADD_ATTR("device_info", DEVICE_, PROFILING_TIMER_OFFSET_AMD);
+#endif
+#ifdef CL_DEVICE_TOPOLOGY_AMD
+    ADD_ATTR("device_info", DEVICE_, TOPOLOGY_AMD);
+#endif
+#ifdef CL_DEVICE_BOARD_NAME_AMD
+    ADD_ATTR("device_info", DEVICE_, BOARD_NAME_AMD);
+#endif
+#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_FREE_MEMORY_AMD);
+#endif
+#ifdef CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD
+    ADD_ATTR("device_info", DEVICE_, SIMD_PER_COMPUTE_UNIT_AMD);
+#endif
+#ifdef CL_DEVICE_SIMD_WIDTH_AMD
+    ADD_ATTR("device_info", DEVICE_, SIMD_WIDTH_AMD);
+#endif
+#ifdef CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD
+    ADD_ATTR("device_info", DEVICE_, SIMD_INSTRUCTION_WIDTH_AMD);
+#endif
+#ifdef CL_DEVICE_WAVEFRONT_WIDTH_AMD
+    ADD_ATTR("device_info", DEVICE_, WAVEFRONT_WIDTH_AMD);
+#endif
+#ifdef CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNELS_AMD);
+#endif
+#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNEL_BANKS_AMD);
+#endif
+#ifdef CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD
+    ADD_ATTR("device_info", DEVICE_, GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD);
+#endif
+#ifdef CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD);
+#endif
+#ifdef CL_DEVICE_LOCAL_MEM_BANKS_AMD
+    ADD_ATTR("device_info", DEVICE_, LOCAL_MEM_BANKS_AMD);
+#endif
+#ifdef CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT
+    ADD_ATTR("device_info", DEVICE_, MAX_ATOMIC_COUNTERS_EXT);
+#endif
+#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
+    ADD_ATTR("device_info", DEVICE_, PARENT_DEVICE_EXT);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_TYPES_EXT);
+    ADD_ATTR("device_info", DEVICE_, AFFINITY_DOMAINS_EXT);
+    ADD_ATTR("device_info", DEVICE_, REFERENCE_COUNT_EXT);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_STYLE_EXT);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("device_info", DEVICE_, LINKER_AVAILABLE);
+    ADD_ATTR("device_info", DEVICE_, BUILT_IN_KERNELS);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_MAX_BUFFER_SIZE);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_MAX_ARRAY_SIZE);
+    ADD_ATTR("device_info", DEVICE_, PARENT_DEVICE);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_MAX_SUB_DEVICES);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_PROPERTIES);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_AFFINITY_DOMAIN);
+    ADD_ATTR("device_info", DEVICE_, PARTITION_TYPE);
+    ADD_ATTR("device_info", DEVICE_, REFERENCE_COUNT);
+    ADD_ATTR("device_info", DEVICE_, PREFERRED_INTEROP_USER_SYNC);
+    ADD_ATTR("device_info", DEVICE_, PRINTF_BUFFER_SIZE);
+#endif
+#ifdef cl_khr_image2d_from_buffer
+    ADD_ATTR("device_info", DEVICE_, IMAGE_PITCH_ALIGNMENT);
+    ADD_ATTR("device_info", DEVICE_, IMAGE_BASE_ADDRESS_ALIGNMENT);
+#endif
+    // device_fp_config
+    ADD_ATTR("device_fp_config", FP_, DENORM);
+    ADD_ATTR("device_fp_config", FP_, INF_NAN);
+    ADD_ATTR("device_fp_config", FP_, ROUND_TO_NEAREST);
+    ADD_ATTR("device_fp_config", FP_, ROUND_TO_ZERO);
+    ADD_ATTR("device_fp_config", FP_, ROUND_TO_INF);
+    ADD_ATTR("device_fp_config", FP_, FMA);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("device_fp_config", FP_, SOFT_FLOAT);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("device_fp_config", FP_, CORRECTLY_ROUNDED_DIVIDE_SQRT);
+#endif
+    // device_mem_cache_type
+    ADD_ATTR("device_mem_cache_type",  , NONE);
+    ADD_ATTR("device_mem_cache_type",  , READ_ONLY_CACHE);
+    ADD_ATTR("device_mem_cache_type",  , READ_WRITE_CACHE);
+    // device_local_mem_type
+    ADD_ATTR("device_local_mem_type",  , LOCAL);
+    ADD_ATTR("device_local_mem_type",  , GLOBAL);
+    // device_exec_capabilities
+    ADD_ATTR("device_exec_capabilities", EXEC_, KERNEL);
+    ADD_ATTR("device_exec_capabilities", EXEC_, NATIVE_KERNEL);
+#ifdef CL_EXEC_IMMEDIATE_EXECUTION_INTEL
+    ADD_ATTR("device_exec_capabilities", EXEC_, IMMEDIATE_EXECUTION_INTEL);
+#endif
+    // command_queue_properties
+    ADD_ATTR("command_queue_properties", QUEUE_, OUT_OF_ORDER_EXEC_MODE_ENABLE);
+    ADD_ATTR("command_queue_properties", QUEUE_, PROFILING_ENABLE);
+#ifdef CL_QUEUE_IMMEDIATE_EXECUTION_ENABLE_INTEL
+    ADD_ATTR("command_queue_properties", QUEUE_, IMMEDIATE_EXECUTION_ENABLE_INTEL);
+#endif
+    // context_info
+    ADD_ATTR("context_info", CONTEXT_, REFERENCE_COUNT);
+    ADD_ATTR("context_info", CONTEXT_, DEVICES);
+    ADD_ATTR("context_info", CONTEXT_, PROPERTIES);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("context_info", CONTEXT_, NUM_DEVICES);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("context_info", CONTEXT_, INTEROP_USER_SYNC);
+#endif
+    // gl_context_info
+#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
+    ADD_ATTR("gl_context_info", , CURRENT_DEVICE_FOR_GL_CONTEXT_KHR);
+    ADD_ATTR("gl_context_info", , DEVICES_FOR_GL_CONTEXT_KHR);
+#endif
+    // context_properties
+    ADD_ATTR("context_properties", CONTEXT_, PLATFORM);
+#if defined(cl_khr_gl_sharing) && (cl_khr_gl_sharing >= 1)
+    ADD_ATTR("context_properties",  ,GL_CONTEXT_KHR);
+    ADD_ATTR("context_properties",  ,EGL_DISPLAY_KHR);
+    ADD_ATTR("context_properties",  ,GLX_DISPLAY_KHR);
+    ADD_ATTR("context_properties",  ,WGL_HDC_KHR);
+    ADD_ATTR("context_properties",  ,CGL_SHAREGROUP_KHR);
+#endif
+#if defined(__APPLE__) && defined(HAVE_GL)
+    ADD_ATTR("context_properties",  ,CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE);
+#endif /* __APPLE__ */
+#ifdef CL_CONTEXT_OFFLINE_DEVICES_AMD
+    ADD_ATTR("context_properties", CONTEXT_, OFFLINE_DEVICES_AMD);
+#endif
+    // command_queue_info
+    ADD_ATTR("command_queue_info", QUEUE_, CONTEXT);
+    ADD_ATTR("command_queue_info", QUEUE_, DEVICE);
+    ADD_ATTR("command_queue_info", QUEUE_, REFERENCE_COUNT);
+    ADD_ATTR("command_queue_info", QUEUE_, PROPERTIES);
+    // mem_flags
+    ADD_ATTR("mem_flags", MEM_, READ_WRITE);
+    ADD_ATTR("mem_flags", MEM_, WRITE_ONLY);
+    ADD_ATTR("mem_flags", MEM_, READ_ONLY);
+    ADD_ATTR("mem_flags", MEM_, USE_HOST_PTR);
+    ADD_ATTR("mem_flags", MEM_, ALLOC_HOST_PTR);
+    ADD_ATTR("mem_flags", MEM_, COPY_HOST_PTR);
+#ifdef cl_amd_device_memory_flags
+    ADD_ATTR("mem_flags", MEM_, USE_PERSISTENT_MEM_AMD);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("mem_flags", MEM_, HOST_WRITE_ONLY);
+    ADD_ATTR("mem_flags", MEM_, HOST_READ_ONLY);
+    ADD_ATTR("mem_flags", MEM_, HOST_NO_ACCESS);
+#endif
+    // channel_order
+    ADD_ATTR("channel_order",  , R);
+    ADD_ATTR("channel_order",  , A);
+    ADD_ATTR("channel_order",  , RG);
+    ADD_ATTR("channel_order",  , RA);
+    ADD_ATTR("channel_order",  , RGB);
+    ADD_ATTR("channel_order",  , RGBA);
+    ADD_ATTR("channel_order",  , BGRA);
+    ADD_ATTR("channel_order",  , INTENSITY);
+    ADD_ATTR("channel_order",  , LUMINANCE);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("channel_order",  , Rx);
+    ADD_ATTR("channel_order",  , RGx);
+    ADD_ATTR("channel_order",  , RGBx);
+#endif
+    // channel_type
+    ADD_ATTR("channel_type",  , SNORM_INT8);
+    ADD_ATTR("channel_type",  , SNORM_INT16);
+    ADD_ATTR("channel_type",  , UNORM_INT8);
+    ADD_ATTR("channel_type",  , UNORM_INT16);
+    ADD_ATTR("channel_type",  , UNORM_SHORT_565);
+    ADD_ATTR("channel_type",  , UNORM_SHORT_555);
+    ADD_ATTR("channel_type",  , UNORM_INT_101010);
+    ADD_ATTR("channel_type",  , SIGNED_INT8);
+    ADD_ATTR("channel_type",  , SIGNED_INT16);
+    ADD_ATTR("channel_type",  , SIGNED_INT32);
+    ADD_ATTR("channel_type",  , UNSIGNED_INT8);
+    ADD_ATTR("channel_type",  , UNSIGNED_INT16);
+    ADD_ATTR("channel_type",  , UNSIGNED_INT32);
+    ADD_ATTR("channel_type",  , HALF_FLOAT);
+    ADD_ATTR("channel_type",  , FLOAT);
+    // mem_object_type
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, BUFFER);
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE2D);
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE3D);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE2D_ARRAY);
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE1D);
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE1D_ARRAY);
+    ADD_ATTR("mem_object_type", MEM_OBJECT_, IMAGE1D_BUFFER);
+#endif
+    // mem_info
+    ADD_ATTR("mem_info", MEM_, TYPE);
+    ADD_ATTR("mem_info", MEM_, FLAGS);
+    ADD_ATTR("mem_info", MEM_, SIZE);
+    ADD_ATTR("mem_info", MEM_, HOST_PTR);
+    ADD_ATTR("mem_info", MEM_, MAP_COUNT);
+    ADD_ATTR("mem_info", MEM_, REFERENCE_COUNT);
+    ADD_ATTR("mem_info", MEM_, CONTEXT);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("mem_info", MEM_, ASSOCIATED_MEMOBJECT);
+    ADD_ATTR("mem_info", MEM_, OFFSET);
+#endif
+    // image_info
+    ADD_ATTR("image_info", IMAGE_, FORMAT);
+    ADD_ATTR("image_info", IMAGE_, ELEMENT_SIZE);
+    ADD_ATTR("image_info", IMAGE_, ROW_PITCH);
+    ADD_ATTR("image_info", IMAGE_, SLICE_PITCH);
+    ADD_ATTR("image_info", IMAGE_, WIDTH);
+    ADD_ATTR("image_info", IMAGE_, HEIGHT);
+    ADD_ATTR("image_info", IMAGE_, DEPTH);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("image_info", IMAGE_, ARRAY_SIZE);
+    ADD_ATTR("image_info", IMAGE_, BUFFER);
+    ADD_ATTR("image_info", IMAGE_, NUM_MIP_LEVELS);
+    ADD_ATTR("image_info", IMAGE_, NUM_SAMPLES);
+#endif
+    // addressing_mode
+    ADD_ATTR("addressing_mode", ADDRESS_, NONE);
+    ADD_ATTR("addressing_mode", ADDRESS_, CLAMP_TO_EDGE);
+    ADD_ATTR("addressing_mode", ADDRESS_, CLAMP);
+    ADD_ATTR("addressing_mode", ADDRESS_, REPEAT);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("addressing_mode", ADDRESS_, MIRRORED_REPEAT);
+#endif
+    // filter_mode
+    ADD_ATTR("filter_mode", FILTER_, NEAREST);
+    ADD_ATTR("filter_mode", FILTER_, LINEAR);
+    // sampler_info
+    ADD_ATTR("sampler_info", SAMPLER_, REFERENCE_COUNT);
+    ADD_ATTR("sampler_info", SAMPLER_, CONTEXT);
+    ADD_ATTR("sampler_info", SAMPLER_, NORMALIZED_COORDS);
+    ADD_ATTR("sampler_info", SAMPLER_, ADDRESSING_MODE);
+    ADD_ATTR("sampler_info", SAMPLER_, FILTER_MODE);
+    // map_flags
+    ADD_ATTR("map_flags", MAP_, READ);
+    ADD_ATTR("map_flags", MAP_, WRITE);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("map_flags", MAP_, WRITE_INVALIDATE_REGION);
+#endif
+    // program_info
+    ADD_ATTR("program_info", PROGRAM_, REFERENCE_COUNT);
+    ADD_ATTR("program_info", PROGRAM_, CONTEXT);
+    ADD_ATTR("program_info", PROGRAM_, NUM_DEVICES);
+    ADD_ATTR("program_info", PROGRAM_, DEVICES);
+    ADD_ATTR("program_info", PROGRAM_, SOURCE);
+    ADD_ATTR("program_info", PROGRAM_, BINARY_SIZES);
+    ADD_ATTR("program_info", PROGRAM_, BINARIES);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("program_info", PROGRAM_, NUM_KERNELS);
+    ADD_ATTR("program_info", PROGRAM_, KERNEL_NAMES);
+#endif
+    // program_build_info
+    ADD_ATTR("program_build_info", PROGRAM_BUILD_, STATUS);
+    ADD_ATTR("program_build_info", PROGRAM_BUILD_, OPTIONS);
+    ADD_ATTR("program_build_info", PROGRAM_BUILD_, LOG);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("program_build_info", PROGRAM_, BINARY_TYPE);
+#endif
+    // program_binary_type
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("program_binary_type", PROGRAM_BINARY_TYPE_, NONE);
+    ADD_ATTR("program_binary_type", PROGRAM_BINARY_TYPE_, COMPILED_OBJECT);
+    ADD_ATTR("program_binary_type", PROGRAM_BINARY_TYPE_, LIBRARY);
+    ADD_ATTR("program_binary_type", PROGRAM_BINARY_TYPE_, EXECUTABLE);
+#endif
+    // kernel_info
+    ADD_ATTR("kernel_info", KERNEL_, FUNCTION_NAME);
+    ADD_ATTR("kernel_info", KERNEL_, NUM_ARGS);
+    ADD_ATTR("kernel_info", KERNEL_, REFERENCE_COUNT);
+    ADD_ATTR("kernel_info", KERNEL_, CONTEXT);
+    ADD_ATTR("kernel_info", KERNEL_, PROGRAM);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("kernel_info", KERNEL_, ATTRIBUTES);
+#endif
+    // kernel_arg_info
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_, ADDRESS_QUALIFIER);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_, ACCESS_QUALIFIER);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_, TYPE_NAME);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_, NAME);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ADDRESS_, GLOBAL);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ADDRESS_, LOCAL);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ADDRESS_, CONSTANT);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ADDRESS_, PRIVATE);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ACCESS_, READ_ONLY);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ACCESS_, WRITE_ONLY);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ACCESS_, READ_WRITE);
+    ADD_ATTR("kernel_arg_info", KERNEL_ARG_ACCESS_, NONE);
+#endif
+    // kernel_work_group_info
+    ADD_ATTR("kernel_work_group_info", KERNEL_, WORK_GROUP_SIZE);
+    ADD_ATTR("kernel_work_group_info", KERNEL_, COMPILE_WORK_GROUP_SIZE);
+    ADD_ATTR("kernel_work_group_info", KERNEL_, LOCAL_MEM_SIZE);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("kernel_work_group_info", KERNEL_, PREFERRED_WORK_GROUP_SIZE_MULTIPLE);
+    ADD_ATTR("kernel_work_group_info", KERNEL_, PRIVATE_MEM_SIZE);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("kernel_work_group_info", KERNEL_, GLOBAL_WORK_SIZE);
+#endif
+    // event_info
+    ADD_ATTR("event_info", EVENT_, COMMAND_QUEUE);
+    ADD_ATTR("event_info", EVENT_, COMMAND_TYPE);
+    ADD_ATTR("event_info", EVENT_, REFERENCE_COUNT);
+    ADD_ATTR("event_info", EVENT_, COMMAND_EXECUTION_STATUS);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("event_info", EVENT_, CONTEXT);
+#endif
+    // command_type
+    ADD_ATTR("command_type", COMMAND_, NDRANGE_KERNEL);
+    ADD_ATTR("command_type", COMMAND_, TASK);
+    ADD_ATTR("command_type", COMMAND_, NATIVE_KERNEL);
+    ADD_ATTR("command_type", COMMAND_, READ_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, WRITE_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, COPY_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, READ_IMAGE);
+    ADD_ATTR("command_type", COMMAND_, WRITE_IMAGE);
+    ADD_ATTR("command_type", COMMAND_, COPY_IMAGE);
+    ADD_ATTR("command_type", COMMAND_, COPY_IMAGE_TO_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, COPY_BUFFER_TO_IMAGE);
+    ADD_ATTR("command_type", COMMAND_, MAP_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, MAP_IMAGE);
+    ADD_ATTR("command_type", COMMAND_, UNMAP_MEM_OBJECT);
+    ADD_ATTR("command_type", COMMAND_, MARKER);
+    ADD_ATTR("command_type", COMMAND_, ACQUIRE_GL_OBJECTS);
+    ADD_ATTR("command_type", COMMAND_, RELEASE_GL_OBJECTS);
+#if PYOPENCL_CL_VERSION >= 0x1010
+    ADD_ATTR("command_type", COMMAND_, READ_BUFFER_RECT);
+    ADD_ATTR("command_type", COMMAND_, WRITE_BUFFER_RECT);
+    ADD_ATTR("command_type", COMMAND_, COPY_BUFFER_RECT);
+    ADD_ATTR("command_type", COMMAND_, USER);
+#endif
+#ifdef cl_ext_migrate_memobject
+    ADD_ATTR("command_type", COMMAND_, MIGRATE_MEM_OBJECT_EXT);
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("command_type", COMMAND_, BARRIER);
+    ADD_ATTR("command_type", COMMAND_, MIGRATE_MEM_OBJECTS);
+    ADD_ATTR("command_type", COMMAND_, FILL_BUFFER);
+    ADD_ATTR("command_type", COMMAND_, FILL_IMAGE);
+#endif
+    // command_execution_status
+    ADD_ATTR("command_execution_status", , COMPLETE);
+    ADD_ATTR("command_execution_status", , RUNNING);
+    ADD_ATTR("command_execution_status", , SUBMITTED);
+    ADD_ATTR("command_execution_status", , QUEUED);
+    // profiling_info
+    ADD_ATTR("profiling_info", PROFILING_COMMAND_, QUEUED);
+    ADD_ATTR("profiling_info", PROFILING_COMMAND_, SUBMIT);
+    ADD_ATTR("profiling_info", PROFILING_COMMAND_, START);
+    ADD_ATTR("profiling_info", PROFILING_COMMAND_, END);
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("profiling_info", MIGRATE_MEM_OBJECT_, HOST);
+    ADD_ATTR("profiling_info", MIGRATE_MEM_OBJECT_, CONTENT_UNDEFINED);
+#endif
+#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
+#endif
+    // affinity_domain_ext
+#if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
+#endif
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("affinity_domain_ext", DEVICE_PARTITION_, EQUALLY);
+    ADD_ATTR("affinity_domain_ext", DEVICE_PARTITION_, BY_COUNTS);
+    ADD_ATTR("affinity_domain_ext", DEVICE_PARTITION_, BY_COUNTS_LIST_END);
+    ADD_ATTR("affinity_domain_ext", DEVICE_PARTITION_, BY_AFFINITY_DOMAIN);
+#endif
+    // device_affinity_domain
+#if PYOPENCL_CL_VERSION >= 0x1020
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, NUMA);
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, L4_CACHE);
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, L3_CACHE);
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, L2_CACHE);
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, L1_CACHE);
+    ADD_ATTR("device_affinity_domain", DEVICE_AFFINITY_DOMAIN_, NEXT_PARTITIONABLE);
+#endif
+#ifdef HAVE_GL
+    // gl_object_type
+    ADD_ATTR("gl_object_type", GL_OBJECT_, BUFFER);
+    ADD_ATTR("gl_object_type", GL_OBJECT_, TEXTURE2D);
+    ADD_ATTR("gl_object_type", GL_OBJECT_, TEXTURE3D);
+    ADD_ATTR("gl_object_type", GL_OBJECT_, RENDERBUFFER);
+    // gl_texture_info
+    ADD_ATTR("gl_texture_info", GL_, TEXTURE_TARGET);
+    ADD_ATTR("gl_texture_info", GL_, MIPMAP_LEVEL);
+#endif
+    // migrate_mem_object_flags_ext
+#ifdef cl_ext_migrate_memobject
+#endif
+
+  }
+
+};