Сбой OpenCL при динамическом линковании?
Я пытаюсь загрузить библиотеку OpenCL во время выполнения, чтобы один и тот же исполняемый файл мог работать на платформах, на которых нет драйверов OpenCL, без поиска неразрешенных символов. Я использую Qt для этого, но я не думаю, что столкнулся с проблемой из-за Qt. Вот моя функция, которая проверяет, установлен ли OpenCL 1.1 или нет:
QLibrary *MyOpenCL::openCLLibrary = NULL;
bool MyOpenCL::loadOpenCL()
{
if(openCLLibrary)
return true;
QLibrary *lib = new QLibrary("OpenCL");
if(!lib->load())
return false;
bool result = false;
typedef cl_int (*MyPlatorms)(cl_uint, cl_platform_id *, cl_uint *);
MyPlatorms pobj = (MyPlatorms) lib->resolve("clGetPlatformIDs");
if(pobj)
{
cl_uint nplatforms = 0;
cl_uint myerr = pobj(0, NULL, &nplatforms);
if((myerr == CL_SUCCESS) && (nplatforms > 0))
{
cl_platform_id *mplatforms = new cl_platform_id[nplatforms];
myerr = pobj(nplatforms, mplatforms, NULL);
typedef cl_int (*MyPlatformInfo)(cl_platform_id, cl_platform_info, size_t, void *, size_t *);
MyPlatformInfo pinfoobj = (MyPlatformInfo) lib->resolve("clGetPlatformInfo");
if(pinfoobj)
{
size_t size;
for(unsigned int i = 0; i < nplatforms; i++)
{
size = 0;
myerr = pinfoobj(mplatforms[i], CL_PLATFORM_VERSION, 0, NULL, &size);//size = 27
if(size < 1)
continue;
char *ver = new char[size];
myerr = pinfoobj(mplatforms[i], CL_PLATFORM_VERSION, size, ver, NULL);
qDebug() << endl << ver;//segmentation fault at this line
...
}
Как можно видеть, Qt успешно разрешил clGetPlatformIDs(). Это даже показало, что есть 1 доступная платформа. Но когда я передаю массив для хранения cl_platform_id, он падает. Почему это происходит?
РЕДАКТИРОВАТЬ: я использую Qt 4.8.1 с компилятором MinGW с использованием OpenCL APP SDK 2.9. Я использую заголовок OpenCL 1.1 с веб-сайта Khronos. Мой ноутбук с 64-битной Windows7 также имеет графический процессор ATI Radeon 7670m с драйверами OpenCL 1.1.
1 ответ
Первый параметр для clGetPlatformIDs
это число элементов, которые драйвер может записать в массив, на который указывает второй элемент.
Если первый вызов, вы передаете INT_MAX и NULL для них. Я ожидаю, что здесь произойдет сбой, потому что вы говорите водителю, чтобы он продолжал и записывал указатель NULL.
Вы должны передать 0 для первого параметра, так как все, что вас интересует, это возвращаемое значение третьего параметра.
Во втором вызове вы, по крайней мере, передаете действительную память для второго параметра, но вы снова передаете INT_MAX. Здесь вы должны пройти nplatforms
так как это то, сколько памяти вы выделили. Для третьего параметра передайте NULL, поскольку вам не нужно возвращаемое значение (снова).