How do i use Lisp/CFFI's defcunion?
Posted: Tue Oct 01, 2013 3:04 am
I'm trying to convert a c union call into lisp....
here is the function I'm trying to convert::
float sum( const CvMat* mat ) {
float s = 0.0f;
for(int row=0; row<mat->rows; row++ ) {
const float* ptr = (const float*)(mat->data.ptr + row * mat->step);
for( col=0; col<mat->cols; col++ ) {
s += *ptr++;
}
}
return( s );
}
the union call is here..
mat->data.ptr
i wrapped the opencv core types_c.h where the the CvMat struct and union are declared
here they are:
typedef struct CvMat
{
int type;
int step;
/* for internal use only */
int* refcount;
int hdr_refcount;
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data;
#ifdef __cplusplus
union
{
int rows;
int height;
};
union
{
int cols;
int width;
};
#else
int rows;
int cols;
#endif
}
CvMat;
when i wrap the types_c.h with swig it outputs the below 2 items for the above:
;; Had to change from SWIG - put data above rows and cols....was below
;; ;(cffi:foreign-type-size '(:struct cv-mat)) = 40
(cffi:defcstruct cv-mat
(type :int)
(step :int)
(refcount :pointer)
(hdr_refcount :int)
(data :pointer)
(rows :int)
(cols :int))
(cffi:defcunion CvMat_data
(ptr :pointer)
(s :pointer)
(i :pointer)
(fl :pointer)
(db :pointer))
when i try and run the defcstruct as:
(cffi:defcstruct cv-mat
(type :int)
(step :int)
(refcount :pointer)
(hdr_refcount :int)
(data (:union CvMat_data))
(rows :int)
(cols :int))
it runs with the defcunion already loaded
so i do this to access the structs slots as a test /with output:
CL-OPENCV> (defparameter mat (create-mat 3 3 +32fc1+))
MAT
CL-OPENCV> (cffi:with-foreign-slots ((type rows cols step hdr_refcount refcount) mat (:struct cv-mat))
(list type rows cols step hdr_refcount refcount))
output> (1111638016 3 3 3 1 #.(SB-SYS:INT-SAP #X7FFFD824C4C0))
CL-OPENCV>
the same call in c outputs:
cout << "type =" << endl << " " << m->type << endl << endl;
cout << "step =" << endl << " " << m->step << endl << endl;
cout << "refcount =" << endl << " " << m->refcount << endl << endl;
cout << "hdr_refcount =" << endl << " " << m->hdr_refcount << endl << endl;
cout << "rows =" << endl << " " << m->rows << endl << endl;
cout << "M = " << endl << " " << m->cols << endl << endl;
type =
1111638016
step =
3
refcount =
0x2332100
hdr_refcount =
1
rows =
3
M =
3
so everything appears even struct wise
by the way my create-mat wrapper is defined as
;; CvMat* cvCreateMat(int rows, int cols, int type)
(cffi:defcfun ("cvCreateMat" create-mat) (:pointer (:struct cv-mat))
(rows :int)
(cols :int)
(type :int))
so i set data to the matrix and acess the elements so you can see data is there:
CL-OPENCV> (defparameter data (cffi:foreign-alloc :float :initial-contents
'(0.0f0 1.0f0 2.0f0 3.0f0 4.0f0 5.0f0 6.0f0 7.0f0 8.0f0)))
DATA
CL-OPENCV> (set-data mat data 12)
; No value
CL-OPENCV> (get-real-2d mat 0 0 )
0.0d0
CL-OPENCV> (get-real-2d mat 0 1 )
1.0d0
CL-OPENCV> (get-real-2d mat 0 2 )
2.0d0
so i attempt to access the data slot of my defcstruct like this and get below error:
(cffi:with-foreign-slots ((data type rows cols
step hdr_refcount refcount) mat (:struct cv-mat))
(list data type rows cols step hdr_refcount refcount))
Execution of a form compiled with errors.
Form:
(SYMBOL-MACROLET ((DATA
(CFFI:FOREIGN-SLOT-VALUE #1=#:PTR1299 '#2=(:STRUCT CV-MAT)
'DATA))
(TYPE (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'TYPE))
(ROWS (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'ROWS))
(COLS (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'COLS))
(STEP (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'STEP))
(HDR_REFCOUNT
(CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'HDR_REFCOUNT))
(REFCOUNT (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'REFCOUNT)))
(LIST DATA TYPE ROWS COLS STEP HDR_REFCOUNT REFCOUNT))
Compile-time error:
Attempt to bind a special variable with SYMBOL-MACROLET: DATA
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
so i try(with the (:union) quoted and unquoted):
(cffi:with-foreign-slots ((data type rows cols step hdr_
refcount refcount) mat '(:union CvMat_data))
(list data type rows cols step hdr_refcount refcount))
and get same above error both with string quoted and unquoted the PTR1299 part of error increments 1 number each time
so if anyone can teach me how 2 do this i would be much appreciative...
here is the function I'm trying to convert::
float sum( const CvMat* mat ) {
float s = 0.0f;
for(int row=0; row<mat->rows; row++ ) {
const float* ptr = (const float*)(mat->data.ptr + row * mat->step);
for( col=0; col<mat->cols; col++ ) {
s += *ptr++;
}
}
return( s );
}
the union call is here..
mat->data.ptr
i wrapped the opencv core types_c.h where the the CvMat struct and union are declared
here they are:
typedef struct CvMat
{
int type;
int step;
/* for internal use only */
int* refcount;
int hdr_refcount;
union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data;
#ifdef __cplusplus
union
{
int rows;
int height;
};
union
{
int cols;
int width;
};
#else
int rows;
int cols;
#endif
}
CvMat;
when i wrap the types_c.h with swig it outputs the below 2 items for the above:
;; Had to change from SWIG - put data above rows and cols....was below
;; ;(cffi:foreign-type-size '(:struct cv-mat)) = 40
(cffi:defcstruct cv-mat
(type :int)
(step :int)
(refcount :pointer)
(hdr_refcount :int)
(data :pointer)
(rows :int)
(cols :int))
(cffi:defcunion CvMat_data
(ptr :pointer)
(s :pointer)
(i :pointer)
(fl :pointer)
(db :pointer))
when i try and run the defcstruct as:
(cffi:defcstruct cv-mat
(type :int)
(step :int)
(refcount :pointer)
(hdr_refcount :int)
(data (:union CvMat_data))
(rows :int)
(cols :int))
it runs with the defcunion already loaded
so i do this to access the structs slots as a test /with output:
CL-OPENCV> (defparameter mat (create-mat 3 3 +32fc1+))
MAT
CL-OPENCV> (cffi:with-foreign-slots ((type rows cols step hdr_refcount refcount) mat (:struct cv-mat))
(list type rows cols step hdr_refcount refcount))
output> (1111638016 3 3 3 1 #.(SB-SYS:INT-SAP #X7FFFD824C4C0))
CL-OPENCV>
the same call in c outputs:
cout << "type =" << endl << " " << m->type << endl << endl;
cout << "step =" << endl << " " << m->step << endl << endl;
cout << "refcount =" << endl << " " << m->refcount << endl << endl;
cout << "hdr_refcount =" << endl << " " << m->hdr_refcount << endl << endl;
cout << "rows =" << endl << " " << m->rows << endl << endl;
cout << "M = " << endl << " " << m->cols << endl << endl;
type =
1111638016
step =
3
refcount =
0x2332100
hdr_refcount =
1
rows =
3
M =
3
so everything appears even struct wise
by the way my create-mat wrapper is defined as
;; CvMat* cvCreateMat(int rows, int cols, int type)
(cffi:defcfun ("cvCreateMat" create-mat) (:pointer (:struct cv-mat))
(rows :int)
(cols :int)
(type :int))
so i set data to the matrix and acess the elements so you can see data is there:
CL-OPENCV> (defparameter data (cffi:foreign-alloc :float :initial-contents
'(0.0f0 1.0f0 2.0f0 3.0f0 4.0f0 5.0f0 6.0f0 7.0f0 8.0f0)))
DATA
CL-OPENCV> (set-data mat data 12)
; No value
CL-OPENCV> (get-real-2d mat 0 0 )
0.0d0
CL-OPENCV> (get-real-2d mat 0 1 )
1.0d0
CL-OPENCV> (get-real-2d mat 0 2 )
2.0d0
so i attempt to access the data slot of my defcstruct like this and get below error:
(cffi:with-foreign-slots ((data type rows cols
step hdr_refcount refcount) mat (:struct cv-mat))
(list data type rows cols step hdr_refcount refcount))
Execution of a form compiled with errors.
Form:
(SYMBOL-MACROLET ((DATA
(CFFI:FOREIGN-SLOT-VALUE #1=#:PTR1299 '#2=(:STRUCT CV-MAT)
'DATA))
(TYPE (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'TYPE))
(ROWS (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'ROWS))
(COLS (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'COLS))
(STEP (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'STEP))
(HDR_REFCOUNT
(CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'HDR_REFCOUNT))
(REFCOUNT (CFFI:FOREIGN-SLOT-VALUE #1# '#2# 'REFCOUNT)))
(LIST DATA TYPE ROWS COLS STEP HDR_REFCOUNT REFCOUNT))
Compile-time error:
Attempt to bind a special variable with SYMBOL-MACROLET: DATA
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]
so i try(with the (:union) quoted and unquoted):
(cffi:with-foreign-slots ((data type rows cols step hdr_
refcount refcount) mat '(:union CvMat_data))
(list data type rows cols step hdr_refcount refcount))
and get same above error both with string quoted and unquoted the PTR1299 part of error increments 1 number each time
so if anyone can teach me how 2 do this i would be much appreciative...