simple callback function

Comments   1   Date Arrow  October 11, 2007 at 10:30pm   User  by mysurface

Callback function is hard to trace, but sometimes it is very useful. Especially when you are designing libraries. Callback function is like asking your user to gives you a function name, and you will call that function under certain condition.

For example, you write a callback timer. It allows you to specified the duration and what function to call, and the function will be callback accordingly. “Run myfunction() every 10 seconds for 5 times”

Or you can create a function directory, passing a list of function name and ask the library to callback accordingly. “Callback success() if success, callback fail() if failed.”

Lets look at a simple function pointer example


void cbfunc()
{
    printf("called");
}

int main ()
{
     /* function pointer */
    void (*callback)(void *);

    /* point to your callback function */
    callback=(void *)cbfunc;

   /* perform callback */
   callback();

   return 0;
}

How to pass argument to callback function?
Observered that function pointer to implement callback takes in void *, which indicates that it can takes in any type of variable including structure. Therefore you can pass in multiple arguments by structure.


typedef struct _myst
{
    int a;
    char b[10];
}myst;

void cbfunc(myst *mt)
{
    fprintf(stdout,"called %d %s.",mt->a,mt->b);
}

int main()
{

    /* func pointer */
    void (*callback)(void *);

    //param
    myst m;
    m.a=10;
    strcpy(m.b,"123");

    /* point to callback function */
    callback = (void*)cbfunc;

    /* perform callback and pass in the param */
    callback(&m);

    return 0;

}

Tagged   fprintf · function pointerComments  Add Your Comment

libcurl - HTTP,ftp,ssh,telnet,ldap client API

Comments   0   Date Arrow  October 7, 2007 at 3:07am   User  by mysurface

curl is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos…), file transfer resume, proxy tunneling and a busload of other useful tricks.

Quote from http://curl.haxx.se/

Advantages of using libcurl:

  • curl is open source.
  • libcurl API support multiple bindings.
  • libcurl is cross platform that supports windows and *nix.
  • API doc of libcurl are easy to follow, it also provides source code examples.
  • You do not need to read up RFC to code for HTTP post or ftp client, you just need to download libcurl-dev and try it out.

    Let me show you one of the simple example source code from curl official site.

    
    /*****************************************************************************
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ | |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
     *                             ___|___/|_| ______|
     *
     * $Id: simple.c,v 1.6 2004/08/23 14:22:52 bagder Exp $
     */
    
    #include <stdio.h>
    #include <curl/curl.h>
    
    int main(void)
    {
      CURL *curl;
      CURLcode res;
    
      curl = curl_easy_init();
      if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
        res = curl_easy_perform(curl);
    
        /* always cleanup */
        curl_easy_cleanup(curl);
      }
      return 0;
    }
    

    Check out the libcurl tutorial and the sample source codes.

    Tagged   libcurlComments  Add Your Comment

    create your own time stamp 2

    Comments   1   Date Arrow  September 27, 2007 at 12:19am   User  by mysurface

    From my previous post, create your own time stamp, I have introduced a way to construct your own time stamp.

    Recently I found a better way, and with this function, you can create a better time stamp, yet the way of construct the time stamp is far more simple compared to my previous post.

    
    #include<stdio.h>
    #include<time.h>
    
    int main()
    {
        char timestamp[100];
        time_t mytime;
        struct tm *mytm;
        mytime=time(NULL);
        mytm=localtime(&mytime);
    
        strftime(timestamp,sizeof timestamp,"%a, %d %b %Y %H:%M:%S %z",mytm);
    
        printf("%s\n",timestamp);
    
        return 0;
    }
    

    Yes, that’s it, and the output is show as below:

    Wed, 26 Sep 2007 23:54:50 +0800

    Tagged   time · localtime · time · strftimeComments  Add Your Comment

    bit specific structure

    Comments   1   Date Arrow  June 2, 2007 at 1:15pm   User  by mysurface

    Sometimes you need to construct a structure which the variables in the structure is not specified in bytes, instead bits. It may occur when you wanna construct some field of a binaries packets for examples Point Code field in Called address of TCAP packet.

    One of the point code format length is 14 bits, consist of 3 parts (x,y,z). Where x is 3 bits, y is 8 bits, and z again 3 bits. How we suppose feed the x,y,z to form a 2 bytes data? 2 bytes is 16 bits, that means 14 bits padding with 2 bits ZERO.

    One of the common solution is write a function with 3 params (x,y,z) to perform shifting bits and returns a 2 bytes characters array. But it is tedious to write such function and the complexity will grows if the number of params increases.

    Therefore, bit specific structure is used instead. To construct a bit specific structure, there are few things have to be taken care precisely.
    1. Variable type used
    2. Whether to use __attribute__((packed)) or not.

    Lets look at the definition of the ERRORNOUS PointCode structure:

    
    typedef struct
    {
         char      x:3,
                   y:8,
                   z:3;
    }PointCode;
    

    The way of define bit specific structure is correct, but the outcome will be errornous.

    
    PointCode pc;
    printf("%d ",sizeof(pc));
    

    The sizeof(pc) will return 3 bytes instead of two bytes. Reason is because, the structure uses variable type that is not large enough to store a 2 bytes data.

    Second attempt will be still ERRORNOUS where we uses unsigned long instead of char.

    
    typedef struct
    {
         unsigned long       x:3,
                             y:8,
                             z:3;
    }PointCode;
    

    unsigned long is 4 bytes, after storing the data, the remaining 2 bytes will be padded with 0. Therefore the sizeof will return 4 bytes, which is not what we wanted, what we want is 2 bytes.

    The CORRECT definition at last:

    
    typedef struct
    {
         unsigned long    x:3,
                          y:8,
                          z:3;
    }__attribute__((packed)) PointCode;
    

    With __attribute__((packed)), it tells the compiler to packed the data, now it returns exactly 14 bits, and sizeof will return 2 bytes. You may want to verify the correctness of the data.

    
    PointCode PC;
    memset(&pc,0,sizeof(pc));
    
    pc.x=1;
    pc.y=2;
    pc.z=3;
    
    unsigned char* ptr=(unsigned char*)&pc;
    
    printf("size(%d) payload: (%X %X) ",sizeof(pc), *ptr, *(ptr+1));
    

    Tagged   c · c++ · bitwiseComments  Add Your Comment

    Pascal Triangle Challenge

    Comments   6   Date Arrow  May 29, 2007 at 10:15pm   User  by mysurface

    A simple challenge for c/c++ fans, use only 2 variable and 2 for loop to print a pascal triangle looks as bellow

    
            1
           121
          12321
         1234321
        123454321
       12345654321
      1234567654321
     123456787654321
    12345678987654321
    

    My solution:

    
    #include<stdio.h>
    #include<stdlib.h>
    
    void piramid(int const c)
    {
        int x,y;
        for(y=0; y<c; y++)
        {
            for(x=0; x<c-(1+y)+((y*2)+1); x++)
            {
                if(x<(c-(y+1)))printf(" ");
                else
                {
                    if(x-(c-(y+2))>y+1) printf("%d",(2*y)+2-(x-(c-(y+2)) ));
                    else printf("%d",(x-(c-(y+1))+1 ));
                }
            }
            printf("\n");
        }
    }
    
    int main(int argc, char* argv[])
    {
        if (argc==2)
        {
    
            if (atoi(argv[1])>9 || atoi(argv[1])<=1)
            {
                printf("Insert range within 2 to 9, ig. %s 9n",argv[0]);
                return 1;
            }
            piramid(atoi(argv[1]));
        }
        else
            printf("Insert range within 2 to 9, ig. %s 9n",argv[0]);
        return 0;
    }
    

    Tagged   c · c++ · quizComments  Add Your Comment

    swap variable quest

    Comments   5   Date Arrow  May 28, 2007 at 10:41pm   User  by mysurface

    This is an interesting quest given by my friend who working in Intel, during our conversation online.

    How to swap two variables ?

    Let say A=123 and B=546, how to swap them. So this is a quest, be smart enough not to give a plain solution like create a temporary variable to swap them. First of all my answer sounds a bit stupid. I say if I coded in python,

    A,B=B,A

    Okay that is not the expecting answer. Before you look at the solution bellow, maybe you would like to try to figure out.

    Hint: use logic XOR, no additional variable is needed.

    Solution:

    A=A XOR B;
    B=A XOR B;
    A=A XOR B;

    Explanation:
    XOR is known as exclusive disjunction where the nature of XOR is when 1 XOR 0 will equal to 1 but when 1 XOR 1 will becomes 0. Another important behavior of XOR is when (a XOR b) XOR b will resulting a.

    So lets look back at the solution, you will find A XOR B seems to become “something else”, where this “something else” will return A if we XOR B and return B if we XOR A. So first line, A=(A XOR B). Secondly B = (A XOR B) XOR B = A, where we replace the original A into (A XOR B). Last line, A= ( A XOR B) XOR A = B. Seems at second line B already become A, so we replace B as A.

    Interesting isn’t it? Look at it few times, if you can’t get it.

    Tagged   c · c++ · bitwiseComments  Add Your Comment

    simple singleton class

    Comments   5   Date Arrow  May 26, 2007 at 12:11pm   User  by mysurface

    Singleton is one of the common design pattern used to make a class object exist only one instant. I have read some books illustrate the implementation of singleton, I found it all complicated. I have tried to come out a very simple example on singleton class, bellow is my outcome.

    
    #include<stdio.h>
    class singleton
    {
        public:
        void print()
        {
            printf("hello\n");
        }
        int a;
    }singleton;
    
    int main()
    {
        //singleton s;  #cannot define a new instant like this anymore.
        singleton.a=5;
        printf("a=%d\n",singleton.a);
        singleton.print();
    
        return 0;
    }
    

    With the class name and the object name appear the same, you make that class object singleton. Which means you can’t instantiate a new object using the name singleton anymore. The way to access the function and variables of a singleton object is direct.

    This is my initial idea of how to make singleton simple.

    Tagged   c++ · design patternComments  Add Your Comment

    nanosleep is better than sleep and usleep

    Comments   1   Date Arrow  May 25, 2007 at 12:48am   User  by mysurface

    Don’t know whether you aware of the example code at Tap the interrupt signal, I am using sleep(1) within endless loop at the first sample of code.

    The example of the code is to illustrate the tapping Interrupt signal while I hit control+c and ignores the termination of the program. When I hit control+c, I discover a problem. the sleep process elapse straight away although its not yet pass a second where it support to sleep for one second.

    It happens to usleep function as well, where both sleep and usleep doesn’t seems to be a good sleep function to use. And I discover a better sleep function from time.h. That is nanosleep. Refers to nanosleep man page, it briefly state that it can cater the problem by storing the remaining time at second param, and with that you can use the remaining to to call nanosleep again.

    That means, its not like sleep or usleep, you can use it straight away. Well, I have write a wrapper for miliseconds sleep. With the signal tap handler function in sample code, use to test for usleep and my own msleep.

    
    #include<stdio.h>
    #include<time.h>
    #include<signal.h>
    
    void sigfunc(int sig_no)
    {
    
    }
    
    int __nsleep(const struct timespec *req, struct timespec *rem)
    {
        struct timespec temp_rem;
        if(nanosleep(req,rem)==-1)
            __nsleep(rem,&temp_rem);
        else
            return 1;
    }
    
    int msleep(unsigned long milisec)
    {
        struct timespec req={0},rem={0};
        time_t sec=(int)(milisec/1000);
        milisec=milisec-(sec*1000);
        req.tv_sec=sec;
        req.tv_nsec=milisec*1000000L;
        __nsleep(&req,&rem);
        return 1;
    }
    
    int main()
    {
        struct sigaction sa={0};
        sa.sa_handler=&sigfunc;
        sigaction(SIGINT, &sa,NULL);
    
        int a=0;
        scanf("%d",&a);
    
        for (;;)
        {
            printf("testing...\n");
            if (a==1)
                msleep(1000);
            else
                usleep(1000000);
        }
        return 1;
    }
    

    __nsleep is a wrapper for nanosleep, the reason I want to do that wrapper is because I want to make a recursive call to nanosleep. If nanosleep is intercept by signal, it will return -1 and the second param will store the remaining time. With that, I call __nsleep recursively passing the second param as first param now. The second param will be a temp timespac structure variable.

    I create another wrapper msleep accepting millisecond, in timespec structure, you can either gives value in nanosecond or second. One thing to be aware is tv_nsec cannot go beyond 999999999, which is 1 second. If beyond that, you have to put it into tv_sec.

    Updates:
    I found __nsleep() is redundant, and I have a better idea without using recursive and __nsleep at all, instead, directly create a msleep.

    
    int msleep(unsigned long milisec)
    {
        struct timespec req={0};
        time_t sec=(int)(milisec/1000);
        milisec=milisec-(sec*1000);
        req.tv_sec=sec;
        req.tv_nsec=milisec*1000000L;
        while(nanosleep(&req,&req)==-1)
             continue;
        return 1;
    }
    

    Store back the remaining time to req, If getting return value -1, continue to sleep. Better and cleaner isn’t it? :D

    Tagged   c · c++ · time · nanosleepComments  Add Your Comment

    Tap the interrupt signal

    Comments   4   Date Arrow  May 20, 2007 at 6:41pm   User  by mysurface

    When you hit control+c, you are actually send a SIGINT ( Interrupt signal ) to your program. By default, your program will be terminated after receiving SIGINT. But you can change the way of handling Interrupt signal.

    Some of the application tends to ignore SIGINT. You can easily do that with sigaction.

    
    #include<stdio.h>
    #include<signal.h>
    void bypass_sigint(int sig_no)
    {
    
    }
    int main()
    {
    
        struct sigaction sa;
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = &bypass_sigint;
        sigaction(SIGINT, &sa,NULL);
    
        while(1)
        {
            sleep(1);
            printf("do nothing \n ");
        }
        return 0;
    }
    

    Create a void function that intentionally do nothing. Create a sigaction structure variable, set the sa_handle point to the void fucntion. At last calling sigaction function, telling the system, while receiving SIGINT, call the void function.

    Observed that the sigaction have to take 3 parameters, and the third param is to store the default sigaction structure for SIGINT. specify NULL for ignoring that.

    What if I wanna tap the interrupt signal, do some operations and then allows the default SIGINT operation carry on? This can be very useful, for example, I want my program to log whatever in my memory to a file before the program terminate.

    
    #include<stdio.h>
    #include<signal.h>
    #include<string.h>
    
    struct sigaction osa;
    
    void bypass_sigint(int sig_no)
    {
        printf("I tap SIGINT and returns back \n");
        sigaction(SIGINT,&osa,NULL);
        kill(0,SIGINT);
    }
    
    int main()
    {
    
        struct sigaction sa,osa;
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = &bypass_sigint;
        sigaction(SIGINT, &sa,&osa);
    
        while(1)
        {
            sleep(1);
            printf("do nothing \n ");
        }
        return 0;
    }
    

    I save the default sigaction structure, and after finish running my handler operation, i reset my sigaction handler to default one and send myself SIGINT.

    Tagged   c · c++ · signal · sigaction · killComments  Add Your Comment

    Non-blocking user input in loop without ncurses.

    Comments   0   Date Arrow  April 8, 2007 at 9:23pm   User  by mysurface

    The title sounds a bit awkward, let my briefly explain what is it all about.

    In my program, I want to wait for user input, but at the same time, I want my other operations keep continue processing. That I define it as non-blocking user input. I want my program to wait for user input in the loop, if receives user input process it and continue wait for next user input, else continue processing other circular operations.

    Usually, people will think about using ncurses library. By using ncurses, you can easily perform non-blocking user input using timeout(0) and getch(). Refers to the ncurses matrix for references.

    What if I don’t want to uses ncurses? Its there any alternatives? Sometimes I just wanna add a function which need non-blocking in a large program, I don’t want to use ncurses because it makes my print line acts differently, or some other reason.

    I have figure out a way, thanks to programmers at ##c@irc.freenode.net. It might look messy and complected, but it works the way I wanted. I uses functions of termios and select, lets look at the functions one by one.

    
    int kbhit()
    {
        struct timeval tv;
        fd_set fds;
        tv.tv_sec = 0;
        tv.tv_usec = 0;
        FD_ZERO(&fds);
        FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
        select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
        return FD_ISSET(STDIN_FILENO, &fds);
    }
    

    This function perform non-blocking checking on the standard input (stdin) without timeout 0, tv.tv_sec and tv.tv_usec both set to zero. select usually uses in the case where there have multiple I/O need to process, or check at the same time. But in this case, I only interested in standard input, therefore only one FD_SET(STDIN_FILENO, &fds) is trigger. For select parameters details, please check out the manual. Seems we are only interested in input, so we place out fd set at second parameter of select(), the 3rd is for output and 4th is for exception.

    Important part, after select if user input is trigger, FD_ISSET will return non zero value, else return 0. So, we now can use it like this

    
        while(!kbhit())
        {
              //do certain operation..
        }
        //user hits enter.
    

    Due to the canonical mode of your terminal, you need to hit enter to confirm your user input. Canonical mode means it always wait for enter to confirms the user input. If that is not your case, bellow is another function to cater that.

    
    void nonblock(int state)
    {
        struct termios ttystate;
    
        //get the terminal state
        tcgetattr(STDIN_FILENO, &ttystate);
    
        if (state==NB_ENABLE)
        {
            //turn off canonical mode
            ttystate.c_lflag &= ~ICANON;
            //minimum of number input read.
            ttystate.c_cc[VMIN] = 1;
        }
        else if (state==NB_DISABLE)
        {
            //turn on canonical mode
            ttystate.c_lflag |= ICANON;
        }
        //set the terminal attributes.
        tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
    
    }
    

    The function name might be misleading, what the function actually does is turn off the canonical mode for stdin. First, get the states of stdin of term. Next turn off the canonical by set 0 to the bits. The line of ttystate.c_cc[VMIN] is set the minimum number of user input to accept. If you set it as 2, the select will wait until 2 character is given, then it will capture as input. At last set the term state. The function actually does allow you to turn on and off the canonical mode.

    Okay, Let see how it apply to work

    
    int main()
    {
        char c;
        int i=0;
    
        nonblock(NB_ENABLE);
        while(!i)
        {
            usleep(1);
            i=kbhit();
            if (i!=0)
            {
                c=fgetc(stdin);
                if (c=='q')
                    i=1;
                else
                    i=0;
            }
    
            fprintf(stderr,"%d ",i);
        }
        printf("\n you hit %c. \n",c);
        nonblock(NB_DISABLE);
    
        return 0;
    }
    

    Press ‘q’ will lead the program to quit, else you will see the print of ‘0′ overwhelming the screen. Observed that I am using usleep(1) inside the loop, without putting usleep, the programs is more responsive, but it uses high CPU resources. On the other hand, putting usleep(1) reduces the CPU resources and also decreases responsiveness of the program. Depend on your needs, you may choose to put it in or not.

    I have make the comparison between this application and a simple ncurses program, this program seems to use lesser memory. Couldn’t measure for CPU resources, as both ps and top shows 0.0 %.

    Curses sample shows as bellow:

    
    #include<stdio.h>
    #include<curses.h>
    #include<unistd.h>
    
    int main ()
    {
        int i=0;
    
        initscr();     //in ncurses
        timeout(0);
        while(!i)
        {
            usleep(1);
            i=getch();
            printw("%d ",i);
            if(i>0)
                i=1;
            else
                i=0;
        }
        endwin();
        printf("\nhitkb end\n");
        return 0;
    }
    

    Download the source code:
    Non-blocking kbhit sample source code.

    Tagged   c · c++ · time · timeval · termios · tcgetattr · tcsetattr · unistd · usleep · selectComments  Add Your Comment