How to 'mix' C and Python?

Discussion in 'Computer Programming, Emulation, and Game Modding' started by Monado_III, Oct 27, 2015.

  1. Monado_III
    OP

    Monado_III GBAtemp Advanced Fan

    Member
    636
    349
    Feb 8, 2015
    Canada
    /dev/null
    My friend and I are wanting to build a program together (it's not a complex program, but not exactly simple either), but we don't know the same languages, I'm 'meh' at C (fairly comfortable with pointers, strings still bug me though) and he's beginning python (but he's smart and picks things up fast so I can teach him more complex concepts to get him off his feet faster), but I was wondering if there was a easy way to build an app using both languages? Would embedding python in C be the way to go?

    (Keep in mind we'll likely need to use stuff like google and apple APIs.)
     
  2. JoostinOnline

    JoostinOnline Certified Crash Test Dummy

    Member
    10,926
    3,701
    Apr 2, 2011
    United States
    The Twilight Zone
    Mixing them is easy. Compiling the bastard combination of code is another thing. ;)

    One of you needs to learn the other language if you want to avoid serious issues, as well as understand the changes the other is making. You learning C would be the much better option since it's a much more powerful language, but him learning Python is simpler. You'll have to work that out on your own.

    What problems are you having with strings? I'll do my best to explain any confusion.
     
    Monado_III likes this.
  3. FAST6191

    FAST6191 Techromancer

    pip Reporter
    23,193
    8,945
    Nov 21, 2005
    If you are thinking something like you might write inline assembly but with python instead then do not, it will not happen in a way that will please either of you. However python and C both speak any number of intermediate methods -- python will happily call a C DLL and vice versa, both will interface with databases in various means (indeed this is a common task for python), command line programs are still very powerful and most OS specific things can also happen.
    What will likely happen is someone will write the main loops of the code in one and the other will take care of various functions. In "normal" programming the slow/less time sensitive parts would be taken care of in python and the things that are slowing the program down would be written in nice fast C, or occasionally in the real world the person that wrote the C has gone or is busy and you need something very simple done right now so you knock it out in python.

    https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages
    http://web.archive.org/web/20071108...-bin/thinki.cgi/UsingPythonWithOtherLanguages

    As for knowing pointers but being hazy on strings that is an odd one, usually I would see it the other way around; pointers are usually the stumbling block for people learning C, strings have their quirks but usually do not pose much trouble.
    I would also suggest you thumb through one of the many excellent python books, I quite like http://greenteapress.com/thinkpython/thinkpython.html
     
    Monado_III likes this.
  4. Monado_III
    OP

    Monado_III GBAtemp Advanced Fan

    Member
    636
    349
    Feb 8, 2015
    Canada
    /dev/null
    Sorry, I worded that badly, pointers for strings is what I have trouble with for whatever reason.

    For example I have a hard time understanding how this works:
    Code:
    /* Program 7.13 Generalizing string input */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    const size_t BUFFER_LEN = 128;              /* Length of input buffer    */
    const size_t NUM_P = 100;                   /* maximum number of strings */
    
    int main(void)
    {
      char buffer[BUFFER_LEN];                  /* Input buffer             */
      char *pS[NUM_P] = { NULL };               /* Array of string pointers */
      char *pbuffer = buffer;                   /* Pointer to buffer        */
      int i = 0;                                /* Loop counter             */
    
      printf("\nYou can enter up to %u messages each up to %u characters.",
                                                      NUM_P, BUFFER_LEN-1);
    
      for(i = 0 ; i<NUM_P ; i++)
      {
        pbuffer = buffer ; /* Set pointer to beginning of buffer */
        printf("\nEnter %s message, or press Enter to end\n",
                                                               i>0? "another" : "a");
    
        /* Read a string of up to BUFFER_LEN characters */
        while((pbuffer - buffer < BUFFER_LEN-1) &&
               ((*pbuffer++ = getchar()) != '\n'));
    
        /* check for empty line indicating end of input */
        if((pbuffer - buffer) < 2)
          break;
    
        /* Check for string too long */
        if((pbuffer - buffer) == BUFFER_LEN && *(pbuffer-1)!= '\n')
        {
          printf("String too long - maximum %d characters allowed.",
                                                          BUFFER_LEN);
          i--;
          continue;
        }
        *(pbuffer - 1) = '\0';                  /* Add terminator             */
    
        pS[i] = (char*)malloc(pbuffer-buffer);  /* Get memory for string      */
        if(pS[i] == NULL)                       /* Check we actually got some…*/
        {
          printf("\nOut of memory - ending program.");
          return 1;                             /* …Exit if we didn't         */
        }
    
        /* Copy string from buffer to new memory */
        strcpy(pS[i], buffer);
      }
    
      /* Output all the strings */
      printf("\nIn reverse order, the strings you entered are:\n");
      while(--i >= 0)
      {
         printf("\n%s", pS[i] );                /* Display strings last to first */
         free(pS[i]);                           /* Release the memory we got     */
         pS[i] = NULL;                    /* Set pointer back to NULL for safety */
      }
      return 0;
    }
    
    but I can easily understand how this works
    Code:
    /* Program 7.11A  Allocating and freeing memory         */
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    
    int main(void)
    {
      unsigned long *primes = NULL;       /* Pointer to primes storage area    */
      unsigned long trial = 0;            /* Integer to be tested              */
    
      bool found = false;                 /* Indicates when we find a prime    */
      size_t total = 0;                   /* Number of primes required         */
      size_t count = 0;                   /* Number of primes found            */
    
      printf("How many primes would you like - you'll get at least 4?  ");
      scanf("%u", &total);                /* Total is how many we need to find */
      total = total<4U ? 4U:total;        /* Make sure it is at least 4        */
    
      /* Allocate sufficient memory to store the number of primes required */
      primes = (unsigned long *)calloc(total, sizeof(unsigned long));
      if (primes == NULL)
      {
         printf("\nNot enough memory. Hasta la Vista, baby.\n");
         return 1;
      }
    
      /* We know the first three primes     */
      /* so let's give the program a start. */
      *primes = 2UL;                      /* First prime                   */
      *(primes+1) = 3UL;                  /* Second prime                  */
      *(primes+2) = 5UL;                  /* Third prime                   */
      count = 3U;                         /* Number of primes stored       */
      trial = 5U;                         /* Set to the last prime we have */
    
      /* Find all the primes required */
      while(count<total)
      {
        trial += 2UL;                     /* Next value for checking       */
    
        /* Try dividing by each of the primes we have       */
        /* If any divide exactly - the number is not prime  */
        for(size_t i = 0 ; i < count ; i++)
          if(!(found = (trial % *(primes+i))))
            break;                        /* Exit if no remainder          */
    
        if(found)                        /* we got one - if found is true */
          *(primes+count++) = trial;     /* Store it and increment count  */
      }
    
      /* Display primes 5-up */
      for(int i = 0 ; i < total ; i ++)
      {
        if(!(i%5U))
          printf("\n");                   /* Newline after every 5         */
        printf ("%12lu", *(primes+i));
      }
      printf("\n");                       /* Newline for any stragglers    */
    
      free(primes);                       /* Release the memory         */
      return 0;
    }
     
  5. Monado_III
    OP

    Monado_III GBAtemp Advanced Fan

    Member
    636
    349
    Feb 8, 2015
    Canada
    /dev/null
    Ok, so I talked to my friend and we decided to both use one language (likely C). thanks for helping.

    btw, does anyone know of any api's to make charts and get financial info (in C)
     
  6. JoostinOnline

    JoostinOnline Certified Crash Test Dummy

    Member
    10,926
    3,701
    Apr 2, 2011
    United States
    The Twilight Zone
    Strings are actually quite similar to pointers in C. Let me try to explain how this code works, where "Line 1" is the first line of main. You may want to copy the code into Programmer's Notepad, Notepad++, or some other text editor with line numbers to follow along. I'll skip the ones that aren't relevant to the main point.

    Line 1: buffer is created, and it is an array (i.e. a list) of 128 (BUFFER_LEN) characters. 128 bytes of memory has been allocated.
    Line 2: pS is created, and it's a array of 100 (NUM_P) null pointers. It is defined as a char, designating that once the pointers have actual values, they will point to either a single character, or an array of characters (so a string). This is where we first see a string behaving like a pointer. When we assign "buffer" to pbuffer, we're actually assigning the address of buffer. It works the same way as:
    Code:
    int var = 5;
    int *ptr = &var; // Calling *ptr later will return 5
    Line 3: pbuffer is created and points to the first character of buffer. We'll be manipulating that later to point to individual characters in buffer.
    Line 9: The for loop is going to run through the array of pointers (pS) that was created in line 2. As long as break is never hit, then every pointer in the pS array will be assigned a value.
    Line 11: This is just resetting pbuffer, since it will be changing during this for loop.
    Line 16: pbuffer and buffer are both the same address right now, so it translates to (0 < BUFFER_LEN-1)
    Line 17: pbuffer is incremented, and whatever character you typed is stored to its target. If the key was Enter, then the loop is broken.
    Line 33: pbuffer-buffer equals the total number of characters, therefore the length of the string. That amount of memory needs to be reserved so that it doesn't get overwritten.


    I should note that this is all called pointer arithmetic, and it is frowned on by some. I usually don't use it because it can yield unexpected results if you do anything wrong. For example, in this case I would have just created an array of strings. It's less efficient memory-wise, but much simpler.
    Code:
    /* Program 7.13 Generalizing string input */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    const size_t MESSAGE_LEN = 128;         /* maximum length of each message */
    const size_t NUM_P = 100;                /* maximum number of strings */
    
    int main(void)
    {
        char ListOfStrings[NUM_P][MESSAGE_LEN] = {{0}}; // Creates 100 strings that are 128 characters long, then fills them with null characters
        int i = 0;                                /* Loop counter             */
        int num = 0;        // Character number in array
    
        printf("\nYou can enter up to %u messages each up to %u characters.", NUM_P, MESSAGE_LEN-1);
    
        for(i = 0 ; i<NUM_P ; i++) {
            num = 0;
            printf("\nEnter %s message, or press Enter to end\n", i>0? "another" : "a");
            while ((num < MESSAGE_LEN-1) && ListOfStrings[i][num] != '\n') {
                ListOfStrings[i][num] = (char)getchar();
                num++;
            };
            if (num == 1) break; // Only one key was entered before the while loop closed, which means it was Enter
        }
    
        /* Output all the strings */
        printf("\nIn reverse order, the strings you entered are:\n");
        while(--i >= 0)
            printf("\n%s", ListOfStrings[i]);       /* Display strings last to first */
      
        return 0;
    }
    In the above, 12800 bytes are always allocated, even if you only type one character, where as the original version only uses what memory is necessary. However, 13KB is an insignificant amount of RAM on computers today, so as long as it isn't something big, you can get by with wasting a tiny bit of space.
     
    Abcdfv and Monado_III like this.
  7. Monado_III
    OP

    Monado_III GBAtemp Advanced Fan

    Member
    636
    349
    Feb 8, 2015
    Canada
    /dev/null
    thanks, that makes much more sense now! :)
     
  8. JoostinOnline

    JoostinOnline Certified Crash Test Dummy

    Member
    10,926
    3,701
    Apr 2, 2011
    United States
    The Twilight Zone
    No problem. If anything is still unclear, don't hesitate to ask.
     
  9. FAST6191

    FAST6191 Techromancer

    pip Reporter
    23,193
    8,945
    Nov 21, 2005
    On this financial info thing I have a few things. What sort of data do you want? You can get delayed feeds with some kind of XML easily enough, though I am not sure what free ones are any good right now (google and yahoo used to both do fairly well here but google pretty much went web only and yahoo is not much better ( https://developer.yahoo.com/finance/ ). Alternatively do you want to speak the FIX protocol ( http://www.fixtradingcommunity.org/pg/main/what-is-fix ) to something? I will link http://www.wikinvest.com/licensing/Faq while I am at it.

    In most cases you will get some kind of XML or database type feed if there is not a C or python library you can use for a given protocol it is probably not worth the effort. If you want to get creative with http://curl.haxx.se/ and similar things you might be able to get something done by fiddling with websites and stripping code, or indeed forget this C lark and make an actual website/HTTP based things.
     
    Monado_III likes this.