My environment: Xcode5, iOS, Objective-C/Objective-C++ mix.
I am trying to figure out what causes the next problem. I am writing my own logging function:
int _me_log(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char *c = va_arg(args, char *);
char *message = NULL;
printf(fmt, args);
int n = asprintf(&message, fmt, args);
if (n != -1 && message != NULL) {
//do something with 'message' like writing to file, etc.
UPDATE:
//we need to handle memory created for 'message' storage.
free(message);
}
va_end(args);
return n;
}
Then I call it like this:
_me_log("socket %s did open", "Socket: 0x1fd1c880");
And instead of correct output socket Socket: 0x1fd1c880 did open I get some gibberish like this socket \\323\331/ did open in this line printf(fmt, args);.
If I call it this way printf("%s", c); I get correct results.
I have googled several implementations (this or this ) of logging functions and functions which pass variable parameters and it seems that I do everything correctly.
Could you please suggest me what I'm doing wrong?
You've got the right idea to use va_list here, but if you work with va_list you should use vasprintf instead of asprintf:
int _me_log(const char *fmt, ...)
{
va_list args;
char *message = NULL;
int n;
va_start(args, fmt);
n = vasprintf(&message, fmt, args);
if (n != -1 && message != NULL) {
// ... use message ...
}
free(message);
va_end(args);
return n;
}
For every routine of the printf family, there is a variant that takes a va_list instead of the variadic argument ... and whose name is prefixed with the letter v, for example:
int printf(const char *format, ...);
int vprintf(const char *format, va_list ap);
These routines exist so you can write you own (non-macro) wrapper for xprintf.
Seems like a very complicated implementation. Try:
int _me_log(const char *fmt, ...) {
int ret = 0;
va_list va;
va_start(va, fmt);
ret = vprintf(fmt, va);
va_end(va);
putc('\n', stdout);
return ret;
}
But, of course, that is no different from printf(), except for forcing a newline.
Related
void gen_rand(unsigned char rand[], int len)
{
time_t time = time();
int i;
for(i=0;i<len;i++)
rand[i] = time+i;
}
void encrypt(unsigned char key[], int ken_len, unsigned char text[], int text_len, unsigned char out[], int &len_out)
{
......
}
void hexdump(unsigned char *buf, int len)
{
......
}
void enc_test(unsigned char text[], int len_text, unsigned char out[], int &out_len)
{
unsigned char key[32];
gen_rand(key,32);
encrypt(key,32,text,32,enc,enc, out_len);
}
int main()
{
int i,out_len,j;
unsigned char text[32];
unsigned char enc[64];
for(i=0;i<65536;i++)
{
for(j=0;j<32;j++) text[j] = i;
enc_test(text,32,enc,out_len);
hexdump(enc,out_len);
sleep(1);
}
}
Above is a sample program in linux. My need is to read the local variable key in function enc_test every time this function runs. Maybe gdb or ptrace is a good option, but this method might significantly slow down the program's speed. Is there a method to monitor and read a local variable when its value changes? How to determine the address of a local variable if ASLR is enabled?
I'm developing a static library that will be distributed to other developers, who may need debug statements. So I have several levels of logging.
In order to avoid constant appearance of
if(loggingLevelCurrentlySet >= loggingLevelWantedForThisInstance){
NSLog(#"log this");
}
I created a set of logging function wrappers. A simplified version looks like this:
void myLog(int logLevel, NSString *format, va_list args){
if((loggingLevelCurrentlySet >= logLevel)){
NSLogv(format, args);
}
}
void myLogLevel1(NSString *format, ...){
va_list args;
va_start(args, format);
myLog(1, format, args);
va_end(args);
}
void myLogLevel2(NSString *format, ...){
va_list args;
va_start(args, format);
myLog(2, format, args);
va_end(args);
}
etc.
But now, I want, from within myLog, access to the fully formated string to do something else with.
void myLog(int logLevel, NSString *format, va_list args){
NSString *fullString = [NSString stringWithFormat:format, args]; //crashes when args is anything but an empty list
CFStringRef cfsr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, format, args); //also crashes
//want to use the string here
if((loggingLevelCurrentlySet >= logLevel)){
NSLogv(format, args);
}
}
NSString *fullString = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
There is a method for that ;)
Although I suggest not to use functions, but some simple macro definitions:
#define myLogLevel1(format, ...) myLog(1, format, __VA_ARGS__)
#define myLogLevel2(format, ...) myLog(2, format, __VA_ARGS__)
I currently use the conversion function which looks like this (C++ Builder):
UnicodeString OutputInCodePage(const int CodePage, std::string& InStr, const unsigned Offs)
{
switch (CodePage)
{
default:
case 0: return AnsiStringT<0> (InStr.substr(Offs).c_str()); // System default
case 037: return AnsiStringT<037> (InStr.substr(Offs).c_str()); // IBM037 IBM EBCDIC US-Canada
case 437: return AnsiStringT<437> (InStr.substr(Offs).c_str()); // IBM437 OEM United States
case 500: return AnsiStringT<500> (InStr.substr(Offs).c_str()); // IBM500 IBM EBCDIC International
// And many more following...
}
}
But I really want to avoid the use of huge switch/case - something like this:
UnicodeString OutputInCodePage(const int CodePage, std::string& InStr, const unsigned Offs)
{
return AnsiStringT<CodePage> (InStr.substr(Offs).c_str());
}
That doesn't work and gives me E2396 Template argument must be a constant expression error.
Is there a way to re-do the code so I can use std::string raw data conversion (into UnicodeString) based on CodePage parameter without a huge switch/case list?
There is indeed a much easier way to handle this - use the RawByteString type and the SetCodePage() function, eg:
UnicodeString OutputInCodePage(const int CodePage, const std::string &InStr, const unsigned Offs)
{
RawByteString out(InStr.c_str() + Offs);
SetCodePage(out, CodePage, false);
return out;
}
Alternatively, use the UnicodeFromLocaleChars() function:
UnicodeString OutputInCodePage(const int CodePage, const std::string &InStr, const unsigned Offs)
{
UnicodeString out;
const char *p_in = InStr.c_str() + Offs;
int in_len = InStr.length() - Offs;
int out_len = UnicodeFromLocaleChars(CodePage, 0, p_in, in_len, NULL, 0);
if (out_len > 0)
{
out.SetLength(out_len);
UnicodeFromLocaleChars(CodePage, 0, p_in, in_len, out.c_str(), out_len);
}
return out;
}
I want to pass ByteArray from ActionScript to C function.
basically I want do something like this:
void init() __attribute__((used,annotate("as3sig:public function init(byteData: ByteArray):int"),
annotate("as3package:example")));
void init()
{
//here I want to pass byteArray data to C variable.
//similar to AS3_GetScalarFromVar(cVar, asVar)
}
Unforunately I cannot find any function in flascc docs to help me with this.
Example:
void _init_c(void) __attribute((used,
annotate("as3sig:public function init(byteData:ByteArray) : void"),
annotate("as3import:flash.utils.ByteArray")));
void _init_c()
{
char *byteArray_c;
unsigned int len;
inline_as3("%0 = byteData.bytesAvailable;" : "=r"(len));
byteArray_c = (char *)malloc(len);
inline_as3("CModule.ram.position = %0;" : : "r"(byteArray_c));
inline_as3("byteData.readBytes(CModule.ram);");
// Now byteArray_c points to a copy of the data from byteData.
// Note that byteData.position has changed to the end of the stream.
// ... do stuff ...
free(byteArray_c);
}
The key here is that the heap in C is exposed on the AS3 side as CModule.ram, which is a ByteArray object.
A pointer malloc'd in C is seen in AS3 as an offset into CModule.ram.
You should use CModule.malloc and CModule.writeBytes methods to manipulate with pointers in C-style manner. Take a look on $FLASCC/samples/06_SWIG/PassingData/PassData.as
void _init_c(void) __attribute((used,
annotate("as3sig:public function init(byteData:ByteArray) : void"),
annotate("as3import:flash.utils.ByteArray")));
void _init_c()
{
char *byteArray_c;
unsigned int len;
inline_as3("%0 = byteData.bytesAvailable;" : "=r"(len));
byteArray_c = (char *) malloc(len);
inline_as3("byteData.readBytes(CModule.ram, %0, %1);" : : "r"(byteArray_c), "r"(len));
// Now byteArray_c points to a copy of the data from byteData.
// Note that byteData.position has changed to the end of the stream.
// ... do stuff ...
free(byteArray_c);
}
We know that we call pthread like this
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void* arg);
However, if in the start_routine function I wanna call has more than one argument, what can I do?
You can put whatever you want into a struct and pass a pointer to that.
In C:
typedef struct {
int a;
int b;
} ChildMainArgs;
void child_main(int a,int b);
void child_main_thread(void *arg)
{
ChildMainArgs *args_ptr = (ChildMainArgs *)arg;
child_main(args_ptr->a,args_ptr->b);
}
ChildMainArgs args;
args.a = 5;
args.b = 7;
pthread_create(..,..,child_main_thread,&args);