How Python calls the C library (Windows & Linux)

Software and hardware environment

  • ubuntu 18.04 64bit

  • windows 10 64bit

  • Python 3.8

  • GCC 4.9

  • visual studio

foreword

In doing pythondevelopment, it is often encountered that it is necessary Cto obtain the corresponding value by calling a dynamic link library of the. This article explains in detail the different implementations on Windowsthe and Linux2 platforms.

Dynamic library for linux

Write a simple Ccode,test.c

#include <stdio.h>
#include <stdlib.h>

char * printStr(const char *p,const char *q)
{
    printf("%s",p);
    printf("%s",q);
    return "djstava";
}

Compile into a dynamic link library by the following command

gcc -fPIC -shared -o libtest.so test.c

call in python3

To call Cfunctions in the library, you need to use ctypesthis module

from ctypes import *

handle = cdll.LoadLibrary('libtest.so')
func = handle.printStr
func.argtypes = (c_char_p,c_char_p)
func.restype = c_char_p
tmp = handle.printStr("hello".encode("utf-8"),"world".encode("utf-8"))
print(tmp.decode("utf-8"))

program execution result

helloworlddjstava

program explanation

func.argtypes = (c_char_p,c_char_p)
func.restype = c_char_p

These two sentences are to set the parameter data type and the return value type respectively. If you do not set it and call it directly, the parameter can be received normally, but the return value will always be a value, and the incoming string parameter must be , otherwise it will only be displayed in intthe encode("utf-8")library c. print as first character

handle = cdll.LoadLibrary('libtest.so')
ret = handle.printStr("hello".encode("utf-8"),"world".encode("utf-8"))

For settings of other data types argtypes, please refer to the links in the references

Windows version of the dynamic library

Visual StudioCompile dll, add before the method that needs to be thrown __declspec(dllexport), such as the following Ccode

__declspec(dllexport) unsigned int crc32( const unsigned char *s, unsigned int len)
{
  unsigned int i;
  unsigned int crc32val=0xffffffff;
 printf("len==%d\n",len);
  for (i = 0;  i < len;  i ++)
      crc32val =  crc32_tab[(crc32val ^ s[i]) & 0xff] ^ ((crc32val >> 8)&0x00FFFFFF);

  return ~crc32val;
}

Then open X64 Native Tools Command Promptthe tool command line prompt, which cannot be used here powershellorcmd

7033cd4157bad8d52a82e0d22439e40d.png

windows ctype

Go to Cthe source code directory and execute the following two commands respectively. The first command is to generate the target file .obj, and the second command is to link the target file to generate a dynamic library, which dllis 64-bit

cl /c crc.c
link /dll crc.obj

At this point, dllthe file is generated, it is the dynamic link library we need, dllthe call sois the same as the method of , so I won’t go into details here

87a3baf5fdd583b4be65287458f93427.jpeg

python call c

Remark

If pythonthe following error is reported when executing the call

File "client.py", line 35, in <module>
    data_crc = CRC.calcStrCRC(recv_buffer[20:], recv_buffer[8] - 14)
  File "D:\longjing\clientdemo\crc.py", line 33, in calcStrCRC
    handle = cdll.LoadLibrary('crc.dll')
  File "D:\tools\anaconda3\lib\ctypes\__init__.py", line 426, in LoadLibrary
    return self._dlltype(name)
  File "D:\tools\anaconda3\lib\ctypes\__init__.py", line 348, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 不是有效的 Win32 应用程序。

There is a high probability that dllthe number of digits does not match. Here is a dllway to check whether it is 32-bit or 64-bit, that is, use Visual Studiothe built-in tooldumpbin

dumpbin /headers libipanelcrc_64bit.dll

81344f6e5792329db80f86758cd63e46.png

windows ctype

References

  • https://docs.python.org/3/library/ctypes.html

Guess you like

Origin blog.csdn.net/djstavaV/article/details/131428024