Posted on 13-03-2013
Filed Under (Technology) by bigbang

If you want to invoke C/C++ third-party library ( third-party libraries are your libraries at the most time ), you just need a script to attach them. At this time, we can use Python ctypes to do this dirty job.

The theme Calling C/C++ from python on StackOverflow has introduced the basic usage of ctypes. The key points are:

  1. If you try to use C library, just load this library and use it.
  2. If you try to use C++ library, you should use keyword extern to wrapper C++ class into functions for C. That means we should put C++ class into C functions, and use keyword extern for statement.

In above two ways, if you get the way to use ctypes to invoke C++ library, then you also get the way to use ctypes to invoke C library. Let’s talk about how to invoke C++ library in details.

For example, there is a C++ class Foo:

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

Then we wrapper out following C style interfaces:

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

We compile the code into library:

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

, then we can use Python to invoke this class. You can put the interfaces into a Python class or use them directly:

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

Everything is OK now. We can invoke this Python class like this:

f = Foo()
f.bar() #and you will see "Hello" on the screen

Under Windows, the process is the same if you try to use Python ctypes, but just need to pay attention to following two points:

  1. When start to link to C/C++ library, it is the best idea to use absolute path to load library.

    When I run above code under Windows, I got following error:

    $ python Linkcpp.py
    Traceback (most recent call last):
      File "Linkcpp.py", line 2, in <module>
        lib = cdll.LoadLibrary('./LinkExample')
      File "C:\Python27\lib\ctypes\__init__.py", line 431, in LoadLibrary
        return self._dlltype(name)
      File "C:\Python27\lib\ctypes\__init__.py", line 353, in __init__
        self._handle = _dlopen(self._name, mode)
    WindowsError: [Error 126]
    

    The reason is that I use following code to load library:

    from ctypes import cdll
    lib = cdll.LoadLibrary('./LinkExample')
    

    We can eliminate this error by changing ./LinkExample into E:/PythonCode/LinkCpp/LinkExample which is library’s absolute path under Windows. We can also use LinkExample if the library is under the same folder as the Python script.

    So, to save the debugging time, it is the best way to do it by using absolute path to load library.

    If you get WindowsError: [Error 126] message, the reason is nothing but two

    • Your DLL is not being located.
    • Your DLL depends on other DLLs that cannot be found.

    PS: The dynamic libraries under Windows has two lib & dll files. In this case, we can just use the name of the library.

  2. If the library is written by C++, then we should use extern to wrapper it.

    In the function stated by extern, we can also use the keyword belongs to C++ which is not in C. For example, we can describe our function like this:

    extern int linkExample(const int index, const char* name);
    

    Python ctypes can run it!

    The method of keyword extern in C++ is complicated. Here we just need to state a function to invoke by C, so we can use keyword const in it.

(0) Comments    Read More   
Posted on 13-03-2013
Filed Under (Technology) by bigbang

The extern keyword in C & C++ is a little complex, by studying from Using extern to Specify Linkage, save it for notes.

The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it’s defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default.

// specifying_linkage1.cpp
int i = 1;
void other();

int main() {
   // Reference to i, defined above:
   extern int i;
}

void other() {
   // Address of global i assigned to pointer variable:
   static int *external_i = &i;

   // i will be redefined; global i no longer visible:
   // int i = 16;
}

In C++, when used with a string, extern specifies that the linkage conventions of another language are being used for the declarator(s). C functions and data can be accessed only if they are previously declared as having C linkage. However, they must be defined in a separately compiled translation unit.

Microsoft C++ supports the strings “C” and “C++” in the string-literal field. All of the standard include files use the extern “C” syntax to allow the run-time library functions to be used in C++ programs.

The following example shows alternative ways to declare names that have C linkage:

// specifying_linkage2.cpp
// compile with: /c
// Declare printf with C linkage.
extern "C" int printf( const char *fmt, ... );

//  Cause everything in the specified header files
//   to have C linkage.
extern "C" {
   // add your #include statements here
   #include <stdio.h>
}

//  Declare the two functions ShowChar and GetChar
//   with C linkage.
extern "C" {
   char ShowChar( char ch );
   char GetChar( void );
}

//  Define the two functions ShowChar and GetChar
//   with C linkage.
extern "C" char ShowChar( char ch ) {
   putchar( ch );
   return ch;
}

extern "C" char GetChar( void ) {
   char ch;

   ch = getchar();
   return ch;
}

// Declare a global variable, errno, with C linkage.
extern "C" int errno;
(0) Comments    Read More   
Posted on 07-03-2013
Filed Under (Technology) by bigbang

Using FFmpeg under Windows, especially using Visual C++, is not very well supported or documented. Today I tried this and mark this down for reference.

1. Download pre-compiled builds or compile from source

The first thing is to download the latest “Shared” and “Dev” builds from Zeranoe FFmpeg builds.

At the time of this writing, the “Dev” builds contain the headers and libs, but not the dlls, so use the “bin” folder of the “Shared” zip.

Note it’s possible to compile FFmpeg (which contains libavcodec) on Windows with MinGW & MSYS, but not with Visual Studio. If you are interesting about compiling FFmpeg on Windows, please check this post.

2. Using libavcodec in Visual Studio

Now configure your project to use the libs, headers and dlls. For the includes, you need to add:

[ffmpeg_directory]\include

Add the corresponding libs under linker options as usual.

[Your_ffmpeg_directory]\lib

3. add missing inttypes.h & stdint.h header file

Even just using libavcodec’s headers requires inttypes.h & stdint.h, and Visual Studio 9/10 doesn’t have it. Download this version and put in your FFmpeg include folder.

[ffmpeg_directory]\include

The most important thing is to add __STDC_CONSTANT_MACROS to Preprocessor, or add following code directly in source file:

#define __STDC_CONSTANT_MACROS

4. Test Code

Since libavcodec is a C library, we have to enclose the #includes in an extern C block. If following code works OK, then you can write more complicated application.

extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

int main( int argc, char* argv[] ) {
    av_register_all();
    return 0;
}

If you want to try more examples, there are a few examples under folder:

[ffmpeg_directory]\doc\examples

It is not complex but just steps!

(4) Comments    Read More   
Posted on 07-03-2013
Filed Under (Technology) by bigbang

1. Get FFmpeg Source Code

It’s recommended to download the release source package of FFmpeg from the official site.

2. Compiling FFmpeg

FFmpeg is developed under Linux, but it can be compiled under most Operating Systems.

For Windows, FFmpeg can be compiled with MSYS and MinGW. If you have setup MSYS and MinGW systems correctly, you can compile FFmpeg under its folder.

MinGW MSYS’s work folder is under the installation path (You can also reconfigure MSYS parameters), on my computer is

C:\MinGW\msys\1.0

Just extract the FFmpeg source code to the home folder under MSYS root path.

First, Cleanup former build results.

make distclean

Second, Setup build parameters.

./configure --enable-shared --disable-yasm --enable-memalign-hack

If there is no error, and config.mak & config.h were generated, you can build the library, and then, if you want, you can install them into the MSYS environment.

make
make install

The compile operation will take a long time.

After installation, you can find the libs and dlls under local folder in MSYS folder, which is

C:\MinGW\msys\1.0\local

on my computer. In MSYS, you can jump into the installation folder by following path:

/usr/local/include
/usr/local/lib

This is the same as on Linux machine.

3. Write FFmpeg test code

There are some example code under /doc/examples, we can use them for test.

(0) Comments    Read More