История изменений
Исправление AITap, (текущая версия) :
Полдня чтения perlxstut, perlxs, perlapi и Google:
1) Создаём скелет модуля: h2xs -Afn My::Module
2) cd My-Module && $EDITOR Module.xs
3) #include<myfile.h>
И пишем обёртку для функции. Например, для «модельного» случая:
typedef struct { int x; int y; } point;
int get_points (point **buf, int cnt);
int get_points (point **buf,int cnt) {
int i;
(*buf)=(point *)malloc(sizeof(point)*cnt);
for (i=0;i<cnt;i++) {
(*buf)[i]=(point){7,7};
}
return cnt;
}
AV *
get_points(int num)
CODE:
// int прозрачно превращается в типы C и обратно
point* buf; // а массивы придётся превращать руками
int cnt = get_points(&buf,num);
// ---
RETVAL = newAV(); // создаём массив
sv_2mortal((SV*)RETVAL); // из-за бага в XS возвращаемые массивы нужно дополнительно делать "смертными"
// ---
int i;
for (i=0;i<cnt;i++) {
AV* arr = newAV(); // создаём массив. его не нужно делать смертным
av_push(arr,newSViv((IV)buf[i].x)); // добавляем в него созданный из int Perl'овый скаляр
av_push(arr,newSViv((IV)buf[i].y));
SV* ref = newRV_noinc((SV*)arr); // получаем ссылку на этот массив
av_push(RETVAL,ref); // и запихиваем её в возвращаемое значение
}
free(buf); // не забываем
OUTPUT:
RETVAL // Perl возвращает ссылку на массив ссылок на массивы
4) Не забываем включить в Makefile.PL:
# Un-comment this if you add C files to link with later:
OBJECT => '$(O_FILES)', # link all the C files too
perl -Iblib/arch -Ilib -MAITap::Module -MData::Dumper -e 'print Dumper AITap::Module::get_points(3)'
$VAR1 = [
[
7,
7
],
[
7,
7
],
[
7,
7
]
];
// Заранее извиняюсь за мой французский C. Я разговариваю на нём со словарём.
Исходная версия AITap, :
Полдня чтения perlxstut, perlxs, perlapi и Google:
1) Создаём скелет модуля: h2xs -Afn My::Module
2) cd My-Module && $EDITOR Module.xs
3) #include<myfile.h>
И пишем обёртку для функции. Например, для «модельного» случая:
typedef struct { int x; int y; } point;
int get_points (point **buf, int cnt);
int get_points (point **buf,int cnt) {
int i;
(*buf)=(point *)malloc(sizeof(point)*cnt);
for (i=0;i<cnt;i++) {
(*buf)[i]=(point){7,7};
}
return cnt;
}
AV *
get_points(int num)
CODE:
// int прозрачно превращается в типы C и обратно
point* buf; // а массивы придётся превращать руками
int cnt = get_points(&buf,num);
// ---
RETVAL = newAV(); // создаём массив
sv_2mortal((SV*)RETVAL); // из-за бага в XS возвращаемые массивы нужно дополнительно делать "смертными"
// ---
int i;
for (i=0;i<cnt;i++) {
AV* arr = newAV(); // создаём массив. его не нужно делать смертным
av_push(arr,newSViv((IV)buf[i].x)); // добавляем в него созданный из int Perl'овый скаляр
av_push(arr,newSViv((IV)buf[i].y));
SV* ref = newRV_noinc((SV*)arr); // получаем ссылку на этот массив
av_push(RETVAL,ref); // и запихиваем её в возвращаемое значение
}
free(buf); // не забываем
OUTPUT:
RETVAL // Perl возвращает ссылку на массив ссылок на массивы
4) Не забываем включить в Makefile.PL:
# Un-comment this if you add C files to link with later:
OBJECT => '$(O_FILES)', # link all the C files too
perl -Iblib/arch -Ilib -MAITap::Module -MData::Dumper -e 'print Dumper AITap::Module::get_points(3)'
$VAR1 = [
[
7,
7
],
[
7,
7
],
[
7,
7
]
];