Function was not declared in the scope - class

I do not know why my program throws me error that I do not have defined functions even though I have them in the program. This happened after adding the code INA219 monitor;
My code:
#include "BNO055_ESP32.h"
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <INA219.h>
#define SHUNT_MAX_V 0.02 /* Rated max for our shunt is 75mv for 50 A current:
we will mesure only up to 20A so max is about 75mV*20/50 lets put some more*/
#define BUS_MAX_V 5 /* with 12v lead acid battery this should be enough*/
#define MAX_CURRENT 5 /* In our case this is enaugh even shunt is capable to 50 A*/
#define SHUNT_R 0.1 /* Shunt resistor in ohm */
#define SERVICE_UUID "6E40180D-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID "6E402A37-B5A3-F393-E0A9-E50E24DCCA9E"
// BLE variables
bool deviceConnected = false;
BLECharacteristic *pCharacteristic;
INA219 monitor;
void setup() {
Wire.begin(21, 22, 400000);
Serial.begin(115200); //opens serial terminal
monitor.begin();
monitor.configure(INA219::RANGE_16V, INA219::GAIN_1_40MV, INA219::ADC_16SAMP , INA219::ADC_16SAMP , INA219::CONT_SH_BUS);
monitor.calibrate(SHUNT_R, SHUNT_MAX_V, BUS_MAX_V, MAX_CURRENT);
BLEDevice::init("SMART HELMET");
//----------BLE INITIALIZATION-------------
// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
}
void loop() {
readQuatData(BNO055_quatCount);
// Calculate the quaternion values
BNO055_quat[0] = (float)(BNO055_quatCount[0]) / 16384.;
BNO055_quat[1] = (float)(BNO055_quatCount[1]) / 16384.;
BNO055_quat[2] = (float)(BNO055_quatCount[2]) / 16384.;
BNO055_quat[3] = (float)(BNO055_quatCount[3]) / 16384.;
pCharacteristic->setValue((uint8_t*)BNO055_quat, 16);
pCharacteristic->notify(); // Send the value to the app!
}
void readQuatData(int16_t * destination)
{
uint8_t rawData[8]; // x/y/z gyro register data stored here
readBytes(BNO055_ADDRESS, BNO055_QUA_DATA_W_LSB, 8, &rawData[0]); // Read the six raw data registers sequentially into data array
destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value
destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ;
destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ;
destination[3] = ((int16_t)rawData[7] << 8) | rawData[6] ;
}
Error I am getting:
C:\Users\Boris\Documents\Arduino\pokus_BNO055_ESP32\BNO_jedna_charka\BNO_jedna_charka.ino: In function 'void loop()':
BNO_jedna_charka:216:36: error: 'readQuatData' was not declared in this scope
readQuatData(BNO055_quatCount);
^
C:\Users\Boris\Documents\Arduino\pokus_BNO055_ESP32\BNO_jedna_charka\BNO_jedna_charka.ino: In function 'void readQuatData(int16_t*)':
BNO_jedna_charka:282:66: error: 'readBytes' was not declared in this scope
readBytes(BNO055_ADDRESS, BNO055_QUA_DATA_W_LSB, 8, &rawData[0]); // Read the six raw data registers sequentially into data array
^
C:\Users\Boris\Documents\Arduino\pokus_BNO055_ESP32\BNO_jedna_charka\BNO_jedna_charka.ino: In function 'bool initBNO055()':
BNO_jedna_charka:346:64: error: 'writeByte' was not declared in this scope
writeByte(BNO055_ADDRESS, BNO055_OPR_MODE, BNO055_CONFIGMODE );
^
C:\Users\Boris\Documents\Arduino\pokus_BNO055_ESP32\BNO_jedna_charka\BNO_jedna_charka.ino: In function 'void accelgyroCalBNO055(float*, float*)':
BNO_jedna_charka:390:49: error: 'writeByte' was not declared in this scope
writeByte(BNO055_ADDRESS, BNO055_PAGE_ID, 0x00);
^
BNO_jedna_charka:401:65: error: 'readBytes' was not declared in this scope
readBytes(BNO055_ADDRESS, BNO055_ACC_DATA_X_LSB, 6, &data[0]); // Read the six raw data registers into data array
^
BNO_jedna_charka:430:65: error: 'readBytes' was not declared in this scope
readBytes(BNO055_ADDRESS, BNO055_GYR_DATA_X_LSB, 6, &data[0]); // Read the six raw data registers into data array
^
C:\Users\Boris\Documents\Arduino\pokus_BNO055_ESP32\BNO_jedna_charka\BNO_jedna_charka.ino: In function 'void magCalBNO055(float*)':
BNO_jedna_charka:530:64: error: 'writeByte' was not declared in this scope
writeByte(BNO055_ADDRESS, BNO055_OPR_MODE, BNO055_CONFIGMODE );
^
exit status 1
'readQuatData' was not declared in this scope
C:\Users\Boris\Documents\Arduino\ina219_pokus_stackoverflow\ina219_pokus_stackoverflow.ino: In function 'void loop()':
ina219_pokus_stackoverflow:45:32: error: 'readQuatData' was not declared in this scope
readQuatData(BNO055_quatCount);
^
C:\Users\Boris\Documents\Arduino\ina219_pokus_stackoverflow\ina219_pokus_stackoverflow.ino: In function 'void readQuatData(int16_t*)':
ina219_pokus_stackoverflow:63:66: error: 'readBytes' was not declared in this scope
readBytes(BNO055_ADDRESS, BNO055_QUA_DATA_W_LSB, 8, &rawData[0]); // Read the six raw data registers sequentially into data array
^
exit status 1
'readQuatData' was not declared in this scope
Thanks for any help.
Boris

In C and C++ you have to declare functions before you call them.
You can either do that by defining the function like you did here:
void readQuatData(int16_t * destination)
{
uint8_t rawData[8]; // x/y/z gyro register data stored here
readBytes(BNO055_ADDRESS, BNO055_QUA_DATA_W_LSB, 8, &rawData[0]); // Read the six raw data registers sequentially into data array
destination[0] = ((int16_t)rawData[1] << 8) | rawData[0] ; // Turn the MSB and LSB into a signed 16-bit value
destination[1] = ((int16_t)rawData[3] << 8) | rawData[2] ;
destination[2] = ((int16_t)rawData[5] << 8) | rawData[4] ;
destination[3] = ((int16_t)rawData[7] << 8) | rawData[6] ;
}
Or you can do it by using a function declaration like this:
void readQuatData(int16_t * destination);
You're calling readQuatData() before you declare it, so you're getting this error.
You can either move your definition of the function before the places that you use it, or you can declare it before you use it, like so:
INA219 monitor;
void readQuatData(int16_t * destination);
void setup() {
I placed it before the call to setup() as declaring everything you need to declare at the start of the file, before the code, is usually cleaner and more maintainable than scattering declarations throughout the code.
You'll need to do this for writeByte() and readBytes(). These seem to be missing from the code you shared, so you're on your own with them, but you'd do the same sort of thing - either define them before you use them, or add a declaration for them before you use them.

Related

[AccelStepper][PlatformIO][mbed] Request for member '' in '', which is of non-class type

so I have been trying to create 3 'accelstepper' objects.
This is a screenshot of my code in case the code section doesn't appear. Also, this is a screenshot of the file "stepper_directory.h"
#include <mbed.h>
#include "stepper_directory.h"
//Include accelstepper library
#include <AccelStepper.h>
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
//Create accelstepper object for the theta axis actuator
AccelStepper taxis(uint8_t interface = AccelStepper::DRIVER, uint8_t tstep = TSTEP, uint8_t tdir = TDIR);
//Create accelstepper object for the magnet actuator
AccelStepper maxis(uint8_t interface = AccelStepper::DRIVER, uint8_t mstep = MSTEP, uint8_t mdir = MDIR);
This is the header file i've used "stepper_directory.h"
#ifndef _STEPPER_DIRECTORY
#define _STEPPER_DIRECTORY
#include "PinNames.h"
//Pin Definitions
#define ZSTEP PA_7
#define ZDIR PA_0
#define TSTEP PA_8
#define TDIR PA_1
#define MSTEP PA_9
#define MDIR PA_2
I've tried to setup one stepper in my main code in main.cpp as follows:
int main() {
// put your setup code here, to run once:
zaxis.setMaxSpeed(188000);
while(1) {
// put your main code here, to run repeatedly:
}
}
But the platformIO compiler is throwing out this lines:
src\main.cpp: In function 'int main()':
src\main.cpp:17:7: error: request for member 'setMaxSpeed' in 'zaxis', which is of non-class type 'AccelStepper(uint8_t, uint8_t, uint8_t)
{aka AccelStepper(unsigned char, unsigned char, unsigned char)}'
zaxis.setMaxSpeed(188000);
^~~~~~~~~~~
*** [.pio\build\nucleo_f410rb\src\main.o] Error 1
I have been attempting to search for what is wrong with my object instantiations to no avail. I would really appreciate if there someone could explain what is wrong with this. This is a screenshot of the error in question
The problem is here.
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
This is a function declaration. It takes three arguments and returns AccelStepper. You cannot initialize an instance of AccelStepper with this line of code.
I assume AccelStepper's constructor is something like this:
AccelStepper AccelStepper(uint8_t interface, uint8_t zstep, uint8_t zdir);
You can initialize your instance this way:
AccelStepper zaxis(AccelStepper::DRIVER, ZSTEP, ZDIR);

TMS320F2812 FatFs f_write returns FR_DISK_ERR

I have problem with an SD card. I'm using the FatFs library ver R0.10b to access the SD card.
My code:
// .... //
FATFS fatfs;
FIL plik;
FRESULT fresult,res1,res2,res3,res4,res5;
UINT zapisanych_bajtow = 0 , br;
UINT zapianie_bajtow = 0;
char * buffor = "123456789abcdef\r\n";
unsigned short int i;
void main(void) {
// ... //
res1 = f_mount(0,&fatfs); // returns FA_OK
res2 = f_open( &plik, "f721.txt", FA_OPEN_ALWAYS | FA_WRITE ); // returns FA_OK
if( res2 == FR_OK )
{
res3 = f_write( &plik, ( const void * ) buffor, 17, &zapisanych_bajtow ); // returns FR_DISK_ERR
}
res4 = f_close( &plik );// returns FR_DISK_ERR
for(;;)
{
}
}
Any idea what might be wrong?
I had similar error with just one difference. I tried to write 4096bytes with f_write function at once. And it always returned FR_DISK_ERR.
And this was caused because I tried to write more then is size of IO buffer in FIL structure in FatFS (defined in ff.h).
typedef struct {
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
WORD id; /* Owner file system mount ID (**do not change order**) */
BYTE flag; /* Status flags */
BYTE err; /* Abort flag (error code) */
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
DWORD dir_sect; /* Sector number containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
BYTE buf[_MAX_SS]; /* File private data read/write window */
} FIL;
The last array buf[_MAX_SS] is the file IO buffer. But _MAX_SS is user defined parameter (defined in ff.h) so you can decrease the amount of bytes written at once or eventually change the _MAX_SS value.
I know this is not your case because you only write 17 bytes at once, but this can be helpful for others.
It's few years when I finished with TMS but maybe it will help you:
FA_OPEN_ALWAYS Opens the file if it is existing. If not, a new file is created.
To append data to the file, use f_lseek() function after file open in this method.
If file does not exists use:
FA_CREATE_NEW Creates a new file. The function fails
with FR_EXIST if the file is existing.
I had the same issue with implementation of Chan FatFs on MSP430- always received FR_DISK_ERR result on calling disk_write().
My reason of the issue was the following:
operation failed on xmit_datablock() call, it returned 0.
xmit_datablock() failed because of xmit_spi_multi() failed.
xmit_spi_multi() failed because it was not enough to just transmit bytes from buffer.
It was necessary to read from RXBUF after every write.
Here it is how it looks after the issue was fixed:
/* Block SPI transfers */
static void xmit_spi_multi (
const BYTE* buff, /* Data to be sent */
UINT cnt /* Number of bytes to send */
)
{
do {
volatile char x;
UCA1TXBUF= *buff++; while(! (UCA1IFG & UCRXIFG)) ; x = UCA1RXBUF;
UCA1TXBUF= *buff++; while(! (UCA1IFG & UCRXIFG)) ; x = UCA1RXBUF;
} while (cnt -= 2);
}
Before fixing the issue there was no read from UCA1RXBUF following every write to UCA1TXBUF.
After fixing xmit_spi_multi() my issue with FR_DISK_ERR in disk_write() was solved.

How to call compat_ioctl or unlocked_ioctl?

I'm trying to implement a driver for RTC (Real Time Clock). I used ioctl function in kernel 2.6.32. It worked fine. But when I run same driver in kernel 3.13.0, it gave an error ‘struct file_operations’ has no member named ‘ioctl’
when I changed ioctl to unlocked_ioctl and compat_ioctl, compiled and moduled inserted.
But calling ioctl in user application not invoking ioctl function in module. What function I have to use in user application to invoke compat_ioctl or unlocked_ioctl?
Check with arguments in driver
define structure file operation Definition like
static struct file_operations query_fops =
{
.owner = THIS_MODULE,
.open = my_open,
.release = my_close,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
.ioctl = my_ioctl
#else
.unlocked_ioctl = my_ioctl
#endif
};
Define ioctl like
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35))
static int my_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg)
#else
static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
#endif
{
switch(cmd){
....................................
...................................
}
}
and application level
No need to do any modification you can follow the basic rule for ioctl at application level.

ensuring data-consistency of object

I'm having a problem with data-consistencies of objects e.g. how to deal with objects that get deleted while the user still has a reference to them.
simple pseudo-code example
node = graph.getNode(name)
node.destroy() < -- node gets destroyed
#or
graph.destroyNode(name)
node.getName() #<-- should complain that we're trying to reference an object that does not exist any more
a simple pseudo-code example would be
struct Node
{
/*...*/
};
typedef boost::shared_ptr<Node> NodePtr;
struct Graph
{
std::map<std::string,NodePtr> nodeMap;
NodePtr getNode(std::string name);
void removeNode(std::string name);
/*...*/
};
typedef boost::shared_ptr<Graph> GraphPtr;
// wrapper arround the the getNode function
object Graph_getNode( object obj, const std::string& key )
{
GraphPtr graphPtr = extract< GraphPtr >(obj);
return boost::python::api::object(graphPtr->getNode(key));
};
class_< Node,boost::noncopyable, NodePtr >( "Node", "node", no_init )
/*....*/
class_< Graph, bases<Node>, boost::noncopyable, GraphPtr >( "Graph", "graph", no_init )
.def("getNode", Graph_getNode, "get a node if it exists")
/*....*/
Are there any functions that I could define which are run on a Node-object every time it gets used where I could check if it is still valid ?
I hope this information is sufficient to understand my problem,
... thanks for reading!
Seb
As Node is exposed as being held by a boost::shared_ptr, the instance's lifetime can be affected by both C++ and Python. Python will keep the C++ Node object alive as long as a handle to the Python object holding the boost::shared_ptr exists.
Therefore, in the following code, lets start with the precondition that a Node named spam is held in graph. The code is annotated with the reference count for the C++ Node instance, as well as the Python Node instance.
# The node named 'spam' is held in
# graph's nodeMap.
# cpp count: 1; python count: 0
# Boost.Python creats a Python Node object
# that holds boost::shared_ptr<Node>.
node = graph.getNode('spam') # cpp count: 2; python count: 1
# Removes the boost::shared_ptr<Node> for
# 'spam' from graph.nodeMap.
graph.destroyNode('spam') # cpp count: 1; python count: 1
# The C++ Node is still alive because the
# Python Node holds a boost::shared_ptr<Node>
node.getName() # cpp count: 1; python count: 1
# When Python no longer has a handle to the
# Python Node object, it will be garbage
# collected, which in turn will destroy
# the held boost::shared_ptr<Node>
node = None # cpp count: 0; python count: 0
If node.getName() should not operate successfully on a destroyed node, then consider explicitly managing state. For example, node.destroy() would set state within node, and member-functions would check state before performing operations. If the state indicates the node has been destroyed, then raise an exception or handle it appropriately.
Here is a basic example demonstrating the lifetime:
#include <map>
#include <string>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
class Node
{
public:
Node(std::string name)
: name_(name)
{
std::cout << "Node()" << std::endl;
}
~Node()
{
std::cout << "~Node()" << std::endl;
}
std::string name() { return name_; }
private:
std::string name_;
};
class Graph
{
public:
// #brief Add node by name.
void add_node(std::string name)
{
nodes_.insert(make_pair(name, boost::make_shared<Node>(name)));
}
/// #brief Destroy node by name.
void destroy_node(std::string name)
{
nodes_.erase(name);
}
// #brief Get node by name.
boost::shared_ptr<Node> get_node(std::string name)
{
nodes_type::iterator result = nodes_.find(name);
return (result != nodes_.end())
? result->second
: boost::shared_ptr<Node>();
}
private:
typedef std::map<std::string, boost::shared_ptr<Node> > nodes_type;
nodes_type nodes_;
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<Node, boost::shared_ptr<Node>,
boost::noncopyable>("Node", python::no_init)
.def("name", &Node::name)
;
python::class_<Graph, boost::noncopyable>("Graph")
.def("add_node", &Graph::add_node)
.def("get_node", &Graph::get_node)
.def("destroy_node", &Graph::destroy_node)
;
}
And its usage in Python:
>>> from example import Graph
>>> graph = Graph()
>>> graph.add_node('spam')
Node()
>>> node = graph.get_node('spam')
>>> print node.name()
spam
>>> graph.destroy_node('spam')
>>> print node.name()
spam
>>> graph = None
>>> node = None
~Node()
Note how Node's destructor was only invoked once Python no longer had a handle to the object.

getting libstruct to work in matlab for dll pointer argument

I'm trying to call a dll function in matlab. I have a C++ struct as shown in sixense.h:
typedef struct _sixenseControllerData {
float pos[3];
float rot_mat[3][3];
float joystick_x;
float joystick_y;
float trigger;
...
} sixenseControllerData;
and functions I could call:
SIXENSE_EXPORT int sixenseInit( void );
SIXENSE_EXPORT int sixenseGetAllNewestData( sixenseAllControllerData * );
I can easily get this to work with calllib('sixense','sixenseInit') since there is no input, but for the function sixenseGetAllNewestData I need to have a struct pointer. I realize that libstruct is what I need to use. However, I don't seem to be doing it right.
So I tried libstruct like so:
libstruct('sixenseControllerData')
and I get the error:
??? Error using ==> feval
Undefined function or variable 'lib.sixenseControllerData'.
Error in ==> libstruct at 15
ptr=feval(['lib.' structtype]);
EDIT: here is my current unedited proto file:
http://pastebin.com/PemmmMqF
the full header file is available here:
https://github.com/rll/sixense/blob/master/include/sixense.h
For C structures, loadlibrary generates types named: s_{NAME} where {NAME} is the name of the structure. In your case we create a pointer as:
s = libstruct('s_sixenseControllerData');
We can see this fact by instructing MATLAB to generate a prototype file:
>> loadlibrary('sixense', 'sixense.h', 'proto','sixense_proto')
A prototype file is a file of MATLAB commands which we can modify and use in place of a header file. In this case, the file will contain something like:
sixense_proto.m
...
structs.s_sixenseControllerData.members = struct('pos', 'single#3', 'rot_mat', 'single#9', 'joystick_x', 'single', 'joystick_y', 'single', 'trigger', 'single', 'buttons', 'uint32', 'sequence_number', 'uint8', 'rot_quat', 'single#4', 'firmware_revision', 'uint16', 'hardware_revision', 'uint16', 'packet_type', 'uint16', 'magnetic_frequency', 'uint16', 'enabled', 'int32', 'controller_index', 'int32', 'is_docked', 'uint8', 'which_hand', 'uint8', 'hemi_tracking_enabled', 'uint8');
structs.s_sixenseAllControllerData.members = struct('controllers', 's_sixenseControllerData#4');
....
Unfortunately, a limitation of loadlibrary is that it does not support nested structure very well, especially if a structure contains a pointer to another structure (or an array in this case):
Nested structures or structures containing a pointer to a structure are
not supported. However, MATLAB can access an array of
structures created in an external library.
So you will not be able to directly create the sixenseAllControllerData structure on the MATLAB side, which is defined in the C header file as:
typedef struct _sixenseAllControllerData {
sixenseControllerData controllers[4];
} sixenseAllControllerData;
According to the following discussion, one workaround is to "unroll"/"flatten" the array into separate variables. You can either do this in a copy of the header file, or making the changes in the generated prototype file (which I think is the preferred way). You can do this without having to recompile the shared library.
In your case, change the nested structure in the generated sixense_proto.m file into:
structs.s_sixenseAllControllerData.members = struct(...
'controllers1', 's_sixenseControllerData', ...
'controllers2', 's_sixenseControllerData', ...
'controllers3', 's_sixenseControllerData', ...
'controllers4', 's_sixenseControllerData');
Now we can create a pointer to this structure, and call the C method:
s = libstruct('s_sixenseAllControllerData');
s.controllers1 = libstruct('s_sixenseControllerData');
s.controllers2 = libstruct('s_sixenseControllerData');
s.controllers3 = libstruct('s_sixenseControllerData');
s.controllers4 = libstruct('s_sixenseControllerData');
out = calllib('sixense', 'sixenseGetAllNewestData', s);
get(s)
A completely different solution is to write a MEX-function to interface with the library. It is just like any other C/C++ code, only using mxArray and the MX-API to interface with MATLAB...
Example:
To test the above, I created a simple DLL with similar structures, and implemented the above solution. Here is the code if someone wants to test it:
helper.h
#ifndef HELPER_H
#define HELPER_H
#ifdef _WIN32
#ifdef EXPORT_FCNS
#define EXPORTED_FUNCTION __declspec(dllexport)
#else
#define EXPORTED_FUNCTION __declspec(dllimport)
#endif
#else
#define EXPORTED_FUNCTION
#endif
#endif
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#include "helper.h"
typedef struct _mystruct {
int pos[3];
double value;
} mystruct;
typedef struct _mystruct2 {
mystruct arr[2];
int num;
} mystruct2;
EXPORTED_FUNCTION void myfunc(mystruct *);
EXPORTED_FUNCTION void myfunc2(mystruct2 *);
#endif
mylib.c
#define EXPORT_FCNS
#include "helper.h"
#include "mylib.h"
void myfunc(mystruct *s)
{
s->pos[0] = 10;
s->pos[1] = 20;
s->pos[2] = 30;
s->value = 4.0;
}
void myfunc2(mystruct2 *s)
{
int i;
for(i=0; i<2; i++) {
myfunc(&(s->arr[i]));
}
s->num = 99;
}
After compiling the above into a DLL, we generate the initial prototype file:
loadlibrary('./mylib.dll', './mylib.h', 'mfilename','mylib_proto')
unloadlibrary mylib
I edit the prototype file as described before:
function [methodinfo,structs,enuminfo,ThunkLibName] = mylib_proto()
MfilePath = fileparts(mfilename('fullpath'));
ThunkLibName = fullfile(MfilePath,'mylib_thunk_pcwin64');
enuminfo = [];
structs = [];
structs.s_mystruct.members = struct('pos','int32#3', 'value','double');
structs.s_mystruct2.members = struct('arr1','s_mystruct', ...
'arr2','s_mystruct', 'num','int32');
ival = {cell(1,0)};
methodinfo = struct('name',ival, 'calltype',ival, 'LHS',ival, ...
'RHS',ival, 'alias',ival, 'thunkname',ival);
methodinfo.thunkname{1} = 'voidvoidPtrThunk';
methodinfo.name{1} = 'myfunc';
methodinfo.calltype{1} = 'Thunk';
methodinfo.LHS{1} = [];
methodinfo.RHS{1} = {'s_mystructPtr'};
methodinfo.thunkname{2} = 'voidvoidPtrThunk';
methodinfo.name{2} = 'myfunc2';
methodinfo.calltype{2} = 'Thunk';
methodinfo.LHS{2} = [];
methodinfo.RHS{2} = {'s_mystruct2Ptr'};
end
Now we can finally invoke functions exposed by the DLL:
%// load library using proto file
loadlibrary('./mylib.dll', #mylib_proto)
%// call first function with pointer to struct
s = struct('pos',[0,0,0], 'value',0);
ss = libstruct('s_mystruct',s);
calllib('mylib', 'myfunc', ss)
get(ss)
%// call second function with pointer to struct containing array of struct
xx = libstruct('s_mystruct2');
xx.arr1 = libstruct('s_mystruct');
xx.arr2 = libstruct('s_mystruct');
calllib('mylib', 'myfunc2', xx)
get(xx)
%// clear references and unload library
clear ss xx
unloadlibrary mylib