Мне было любопытно, смогу ли я обмануть массив Chapel, чтобы он ссылался на буфер, выделенный в C, без особых усилий.Я смог это сделать, но не горжусь результатом.В частности:
- он использует функции, которые не предназначены для пользователя, поэтому может измениться или сломаться в любой момент в будущем
- в настоящее время он работает только для прямоугольных массивов Часовни, которые начинают индексирование с 0в каждом измерении
Имея в виду эти предостережения, вот простой C-заголовок, который предоставляет несколько простых процедур, вызываемых из Chapel.Первый выделяет тривиальный массив из 9 элементов;вторая освобождает свой аргумент.
#include <stdlib.h>
double* getDataPtr() {
double* dataPtr = (double*)malloc(9*sizeof(double));
dataPtr[0] = 1.1;
dataPtr[1] = 1.2;
dataPtr[2] = 1.3;
dataPtr[3] = 2.1;
dataPtr[4] = 2.2;
dataPtr[5] = 2.3;
dataPtr[6] = 3.1;
dataPtr[7] = 3.2;
dataPtr[8] = 3.3;
return dataPtr;
}
void freeDataPtr(double* ptr) {
free(ptr);
}
, и вот код Чапеля, который вызывает его, затем принудительно указывает указатель C в существующий массив соответствующего размера и индексы на основе 0:
//
// Declare a Chapel array. Note that this program will only work as
// written if it uses 0-based indexing.
//
var A: [0..2, 0..2] real;
//
// testit.h is the C code above. It defines a simple C stub that returns a pointer
// to floating point data.
//
require "testit.h";
//
// Here are the key routines that testit.h exposes back to Chapel to
// get and free a pointer to floating point data.
//
extern proc getDataPtr(): c_ptr(real);
extern proc freeDataPtr(ptr: c_ptr(real));
//
// Grab the pointer from C
//
const myCPtr = getDataPtr();
//
// Save two pointer values defined in A's descriptor. Note that these
// are not part of its public interface, so are not recommended for
// typical users and could change / break at any future point.
//
const saveData = A._value.data;
const saveShiftedData = A._value.shiftedData;
//
// Replace these pointers with the one we got from C.
//
A._value.data = (myCPtr: _ddata(real));
A._value.shiftedData = (myCPtr: _ddata(real));
//
// print out A, "proving" that we're referring to the data from C
//
writeln(A);
//
// restore the original pointers to avoid having Chapel try to free
// the C memory / leak the Chapel memory.
//
A._value.data = saveData;
A._value.shiftedData = saveShiftedData;
//
// Free the C data
//
freeDataPtr(myCPtr);
Вывод заявления writeln(A)
Чапеля:
1.1 1.2 1.3
2.1 2.2 2.3
3.1 3.2 3.3
Я думаю, что было бы вполне разумно подать запрос на добавление функции на странице *1039* GitHub Чапеля , предлагающей лучшего пользователяинтерфейс для принятия указателя C, как этот, хотя и в более хорошем и официальном виде.