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

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);

Related

Function was not declared in the scope

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.

How to add a built-in module to a C-Python API after Py_Initialize?

I have a module defined in my C code like so:
static struct PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"the_module_name", /* m_name */
module_documentation, /* m_doc */
//....
};
and a function to initialize it:
PyMODINIT_FUNC init_the_module(void)
{
PyObject *mod, *submodule;
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
mod = PyModule_Create(&module_def);
PyModule_AddObject(mod, "some_submodule", (submodule = init_the_submodule()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
// more submodules..
return mod;
}
The application that I am embedding python into is quite big and I can not change the workflow much. At this point Py_Initialize has already been called, so I can not call PyImport_ExtendInittabor PyImport_AppendInittab .
How can I create and add the module to the system modules?
Maybe I can manipulate the modules dictionary directly? Like so:
PyObject *modules, *the_module;
modules = PyImport_GetModuleDict();
PyDict_SetItemString(modules, "the_module_name", init_the_module());
the_module = PyDict_GetItemString(modules, "the_module_name"); //this is getting something back
std::cout << PyDict_Size(the_module) << std::endl; // this prints -1
The easiest way to handle this is to statically initialize your statically-linked modules by directly calling initspam() after the call to Py_Initialize() or PyMac_Initialize():
int main(int argc, char **argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initspam();
An example may be found in the file Demo/embed/demo.c in the Python source distribution.

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

Creating Threaded callbacks in XS

EDIT: I have created a ticket for this which has data on an alternative to this way of doing things.
I have updated the code in an attempt to use MY_CXT's callback as gcxt was not storing across threads. However this segfaults at ENTER.
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifndef aTHX_
#define aTHX_
#endif
#ifdef USE_THREADS
#define HAVE_TLS_CONTEXT
#endif
/* For windows */
#ifndef SDL_PERL_DEFINES_H
#define SDL_PERL_DEFINES_H
#ifdef HAVE_TLS_CONTEXT
PerlInterpreter *parent_perl = NULL;
extern PerlInterpreter *parent_perl;
#define GET_TLS_CONTEXT parent_perl = PERL_GET_CONTEXT;
#define ENTER_TLS_CONTEXT \
PerlInterpreter *current_perl = PERL_GET_CONTEXT; \
PERL_SET_CONTEXT(parent_perl); { \
PerlInterpreter *my_perl = parent_perl;
#define LEAVE_TLS_CONTEXT \
} PERL_SET_CONTEXT(current_perl);
#else
#define GET_TLS_CONTEXT /* TLS context not enabled */
#define ENTER_TLS_CONTEXT /* TLS context not enabled */
#define LEAVE_TLS_CONTEXT /* TLS context not enabled */
#endif
#endif
#include <SDL.h>
#define MY_CXT_KEY "SDL::Time::_guts" XS_VERSION
typedef struct {
void* data;
SV* callback;
Uint32 retval;
} my_cxt_t;
static my_cxt_t gcxt;
START_MY_CXT
static Uint32 add_timer_cb ( Uint32 interval, void* param )
{
ENTER_TLS_CONTEXT
dMY_CXT;
dSP;
int back;
ENTER; //SEGFAULTS RIGHT HERE!
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(interval)));
PUTBACK;
if (0 != (back = call_sv(MY_CXT.callback,G_SCALAR))) {
SPAGAIN;
if (back != 1 ) Perl_croak (aTHX_ "Timer Callback failed!");
MY_CXT.retval = POPi;
} else {
Perl_croak(aTHX_ "Timer Callback failed!");
}
FREETMPS;
LEAVE;
LEAVE_TLS_CONTEXT
dMY_CXT;
return MY_CXT.retval;
}
MODULE = SDL::Time PACKAGE = SDL::Time PREFIX = time_
BOOT:
{
MY_CXT_INIT;
}
SDL_TimerID
time_add_timer ( interval, cmd )
Uint32 interval
void *cmd
PREINIT:
dMY_CXT;
CODE:
MY_CXT.callback=cmd;
gcxt = MY_CXT;
RETVAL = SDL_AddTimer(interval,add_timer_cb,(void *)cmd);
OUTPUT:
RETVAL
void
CLONE(...)
CODE:
MY_CXT_CLONE;
This segfaults as soon as I go into ENTER for the callback.
use SDL;
use SDL::Time;
SDL::init(SDL_INIT_TIMER);
my $time = 0;
SDL::Timer::add_timer(100, sub { $time++; return $_[0]} );
sleep(10);
print "Never Prints";
Output is
$
it should be
$ Never Prints
Quick comments:
Do not use Perl structs (SV, AV, HV, ...) outside of the context of a Perl interpreter object. I.e. do not use it as C-level static data. It will blow up in a threading context. Trust me, I've been there.
Check out the "Safely Storing Static Data in XS" section in the perlxs manpage.
Some of that stuff you're doing looks rather non-public from the point of view of the perlapi. I'm not quite certain, though.
$time needs to be a shared variable - otherwise perl works with separate copies of the variable.
My preferred way of handling this is storing the data in the PL_modglobal hash. It's automatically tied to the current interpreter.
We have found a solution to this using Perl interpreter threads and threads::shared. Please see these
Time.xs
Also here is an example of a script using this code.
TestTimer.pl

Drawing currency symbol

How to draw a currency symbol in a custom label using CGContextShowTextAtPoint method in draw rect.
Here the symbol is in string format.
Any help!!
Thanks
You have to resort to C style strings, since this is what CGContextShowTextAtPoint() requires. In order to correctly handle the locale (the currency symbol changes with the locale) you must use setlocale(), then you format your string using strfmon() and finally you pass the string created with strfmon() to CGContextShowTextAtPoint().
Documentation is available as follows from the terminal:
man 3 setlocale
man 3 strfmon
EDIT/UPDATE: For your information, strfmon() internally uses struct lconv. The structure can be retrieved with the function localeconv(). See man 3 localeconv for a detailed description of the fields available in the structure.
for instance, try the following simple C program setting different locales
#include <stdio.h>
#include <locale.h>
#include <monetary.h>
int main(void)
{
char buf[BUFSIZ];
double val = 1234.567;
/* use your current locale */
setlocale(LC_ALL, "");
/* uncomment the next line and try this to use italian locale */
/* setlocale(LC_ALL, "it_IT"); */
strfmon(buf, sizeof buf, "You owe me %n (%i)\n", val, val);
fputs(buf, stdout);
return 0;
}
The following uses localeconv():
#include <stdio.h>
#include <limits.h>
#include <locale.h>
int main(void)
{
struct lconv l;
int i;
setlocale(LC_ALL, "");
l = *localeconv();
printf("decimal_point = [%s]\n", l.decimal_point);
printf("thousands_sep = [%s]\n", l.thousands_sep);
for (i = 0; l.grouping[i] != 0 && l.grouping[i] != CHAR_MAX; i++)
printf("grouping[%d] = [%d]\n", i, l.grouping[i]);
printf("int_curr_symbol = [%s]\n", l.int_curr_symbol);
printf("currency_symbol = [%s]\n", l.currency_symbol);
printf("mon_decimal_point = [%s]\n", l.mon_decimal_point);
printf("mon_thousands_sep = [%s]\n", l.mon_thousands_sep);
printf("positive_sign = [%s]\n", l.positive_sign);
printf("negative_sign = [%s]\n", l.negative_sign);
}
I don't really get what you're asking,
checking the documentation, the method would look something like that:
CGContextRef ctx = UIGraphicsGetCurrentContext();
const char *string = "$";
CGContextShowTextAtPoint (ctx, 160, 240, string, 1);
Haven't tested it, but this should draw $ in the center of the screen.
BTW, why not use images?
~ Natanavra.