How do I get a C++ structure 'behind' a libpointer?
14 views (last 30 days)
Show older comments
Hi there
I'm using an old 7.5.0/R2007b version of Matlab, and I'm experiencing a problem when reading structures created by an external C++ function.
I'm calling the function
struct_new* GetStruct_new(uint16 const val);
via loadlibrary and calllib. I'm also using a prototype file to circumvent a packing problem I had some months ago.
The structure is declared as follows in C++ code:
typedef struct
{
float32 u16_Upper;
float32 u16_Lower;
float32* pf32_Parameters;
}
match_s;
typedef struct
{
uint16 u16_Start;
uint16 u16_End;
match_s* ps_1st_Match;
match_s* ps_2nd_Match;
}
results_s;
typedef struct
{
uint16 u16_Depth;
uint16 u16_Width;
uint16 u16_Height;
uint16* pu16_InData;
uint16* pu16_OutData;
results_s s_Results[256];
uint8 bla[256];
uint8* blubb[256];
}
struct_new;
...and in the prototype file:
structs.match_s.packing=4;
structs.match_s.members=struct('u16_ED_Upper', 'single', 'u16_ED_Lower', 'single', 'pf32_ED_Parameters', 'singlePtr');
structs.results_s.packing=4;
structs.results_s.members=struct('u16_Start', 'uint16', 'u16_End', 'uint16', 'ps_1st_Match', 'match_sPtr', 'ps_2nd_Match', 'match_sPtr');
structs.struct_new.packing=4;
structs.struct_new.members=struct('u16_Depth', 'uint16', 'u16_Width', 'uint16', 'u16_Height', 'uint16', 'pu16_InData', 'uint16Ptr', 'pu16_OutData', 'uint16Ptr', 's_Results', 'results_s#256', 'bla', 'uint8#256', 'blubb', 'uint8Ptr#256');
In Matlab I do the following:
>> addpath ('\\projects\Binford\KX-2500\')
>> loadlibrary ('KX_drives.dll', @KX-2500, 'alias', 'KX');
>> params = calllib('KX', 'GetStruct_new', 11);
>> par = get(params, 'Value');
>> par.s_Results
ans =
libpointer
This libpointer is my problem, as I have no clue how to resolve it into an array of s_Result structures and read/write them. I've searched the documentation, but I wasn't able to find something that could help me on this one; most exapmles were about creating pointers, not the opposite way.
Thanks in advance!
0 Comments
Accepted Answer
Philip Borghesani
on 13 Mar 2012
Given:
structs.struct_new.members=struct('u16_Depth', 'uint16', 'u16_Width', 'uint16', 'u16_Height', 'uint16', 'pu16_InData', 'uint16Ptr', 'pu16_OutData', 'uint16Ptr', 's_Results', 'results_s#256', 'bla', 'uint8#256', 'blubb', 'uint8Ptr#256');
I expect you are getting some warnings when you call loadlibrary. Loadlibrary cannot properly process 'results_s#256' or 'uint8Ptr#256 your options are to redeclare these fields as a vector of a basic data type or change your structure.
For structures this complex you may be better off with a mex file or writing a helper dll that can access the structure and return its members or pointers to the desired members.
More Answers (3)
Ampere Kui
on 19 Feb 2012
You will need to cast the data into something that Matlab can understand.
addpath ('\\projects\Binford\KX-2500\')
loadlibrary ('KX_drives.dll', @KX-2500, 'alias', 'KX');
params = calllib('KX', 'GetStruct_new', 11);
par = get(params, 'Value');
tmp = par.s_Results;
% Assuming setdatatype works on variable tmp.
setdatatype(tmp, 'uint8Ptr');
% The struct s_Results has the following data structure:
% 2 bytes
% 2 bytes
% 4 bytes memory address (8 bytes if you are on 64-bit system)
% 4 bytes memory address (8 bytes if you are on 64-bit system)
m = getfield(libstruct('results_s'), structsize);
bytes = numel(tmp.value);
n = bytes /m;
% Resize the output so that each column corresponds to one structure.
v = reshape(tmp.value, m, n);
% Obtain all the u16_Start and u16_End variables. Note that you won't be able to get libpointer to ps_1st_Match and ps_wnd_Match this way.
toVector = @(x) x(:);
u16_Start = typecast(toVector(v(1:2,:)), 'uint16');
u16_End = typecast(toVector(v(3:4,:)), 'uint16');
Alternately, you can copy each column into a libstruct of type results_s to obtain the entire structure. If you have a function foo() that returns a pointer to one results_s structure, then you can try this:
% Copy one column of data from v to the libpointer from foo().
s = calllib('KX', 'foo');
setdatatype(s, 'uint8Ptr');
s.value = v(:,1);
setdatatype(s, 'results_sPtr');
% The structure in the first cell of the array:
disp(s.value);
0 Comments
Kaustubha Govind
on 19 Dec 2011
Do you get anything useful by trying:
par.s_Results.Value;
0 Comments
See Also
Categories
Find more on Call C from MATLAB in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!