我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python使用Ctypes与C/C++

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python使用Ctypes与C/C++

项目中可能会经常用到第三方库,主要是出于程序效率考虑和节约开发时间避免重复造轮子。无论第三方库开源与否,编程语言是否与当前项目一致,我们最终的目的是在当前编程环境中调用库中的方法并得到结果或者借助库中的模块实现某种功能。这个过程会牵涉到很多东西,本篇文章将简要的介绍一下该过程的一些问题。

1.背景

多语言混合编程可以弥补某一种编程语言在性能表现或者是功能等方面的不足。虽然所有的高级语言都会最终转换成汇编指令或者最底层的机器指令,但是语言本身之间的千差万别很难一言以蔽之,这对不同语言之间相互通信造成很大的障碍。

工作中需要用python完成一项功能,但是所有现有的python库都不满足需求。最终找到了一个开源的C++库,编译得到动态库被python调用才完成工作需求。虽然整个过程耗时不多,但是期间碰到很多的问题,而且这些问题都很有思考价值。

除了这篇博文外,后续还将有一到两篇文章通过具体的实例讲解一下跨语言调用。

2.问题思考

在进行具体的介绍之前,先来思考一下调用外部库或者自己实现库所牵涉的一些一般性的问题。这样或许实际中操作使用时会理解的更加深刻,遇到问题也能够逐项的排查。

如果用C语言写的库调用了Linux的system call,纵使C本身是跨平台的,那么该库也不可能在Window上被使用,即便我们能拿到源码。这里有两个核心问题:

  • 是否开源
  • 是否跨平台

如果库的实现不依赖平台,且开源,那就意味着很大可能能在当前项目中使用。为什么是可能,因为即使库的实现语言和当前项目语言一致,也可能因为语言版本差异或者标准迭代导致不兼容。

 最差的情况就是只能拿到编译后的库文件,且需在特定的平台运行。

作为库的开发者,最好是能够开源且库的实现不依赖于特定的平台,这样才能最大限度的被使用。

作为库的使用者,最不理想的情况是库可以在当前平台使用,但是只能拿到静态库或者动态库,且库的实现语言和当前项目语言不一致。

多数情况是第三方库是跨平台的且能够拿到源代码。这样的话如果两者的实现语言一致,我们可以直接将第三方库的代码移植到当前的项目中;如果实现语言不一致,需要在当前平台上将库的源码编译出当前平台上可用的库文件,然后在当前项目中引用编译生成的库文件。

本文将先简单的介绍在window平台上,使用python 2.7 自带的ctypes库引用标准的C动态库msvcrt.dll。这里可以先思考以下几个问题:

  1. python可不可以引用静态库?
  2. python中怎么拿到DLL导出的函数?
  3. python和C/C++之间的变量的类型怎样转换,如果是自定义的类型呢?
  4. 怎么处理函数调用约定(calling convention,eg:__cdecl,__stdcall,__thiscall,__fastcall)可能不同的问题?
  5. 如果调用DLL库的过程中出现问题,是我们调用的问题还是库本身的问题?应该怎样快速排查和定位问题?
  6. 有没有什么现有的框架能够帮我们处理python中引用第三方库的问题呢?
  7. 对于自定义的类型(class 和 struct)是否能在python中被引用。

关于函数调用约定,有必要简单的提一下:

Calling Convention和具体的编程语言无关,是由编译器、连接器和操作系统平台这些因素共同决定的。

The Visual C++ compilers allow you to specify conventions for passing arguments and return values between functions and callers. Not all conventions are available on all supported platforms, and some conventions use platform-specific implementations. In most cases, keywords or compiler switches that specify an unsupported convention on a particular platform are ignored, and the platform default convention is used.

这是MS的官方解释。注意最后一句话,表示对于函数调用,在平台不支持的情况下,语言中指定关键字或者编译器转换均可能无效。

接下的介绍中来我们将一一回答上面的问题。

3.导入C标准动态库

先来简单看一下python中如何引用C的标准动态库。

 1 import ctypes, platform, time
 2 if platform.system() == 'Windows':
 3     libc = ctypes.cdll.LoadLibrary('msvcrt.dll')
 4 elif platform.system() == 'Linux':
 5     libc = ctypes.cdll.LoadLibrary('libc.so.6')
 6 print libc
 7 # Example 1
 8 libc.printf('%s\n', 'lib c printf function')
 9 libc.printf('%s\n', ctypes.c_char_p('lib c printf function with c_char_p'))
10 libc.printf('%ls\n', ctypes.c_wchar_p(u'lib c printf function with c_wchar_p'))
11 libc.printf('%d\n', 12)
12 libc.printf('%f\n', ctypes.c_double(1.2))
13 # Example 2
14 libc.sin.restype = ctypes.c_double
15 print libc.sin(ctypes.c_double(30 * 3.14 / 180))
16 # Example 3
17 libc.pow.restype = ctypes.c_double
18 print libc.pow(ctypes.c_double(2), ctypes.c_double(10))
19 # Example 4
20 print libc.time(), time.time()
21 # Example 5
22 libc.strcpy.restype = ctypes.c_char_p
23 res = 'Hello'
24 print libc.strcpy(ctypes.c_char_p(res), ctypes.c_char_p('World'))
25 print res

接下来我们一一分析上面的这段代码。

3.1 加载库的方式

根据当前平台分别加载Windows和Linux上的C的标准动态库msvcrt.dll和libc.so.6。

 注意这里我们使用的ctypes.cdll来load动态库,实际上ctypes中总共有以下四种方式加载动态库:

  1. class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)
  2. class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)
  3. class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)
  4. class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)

关于这几个加载动态库的方式区别细节可以参考一下官网的说明,这里仅简要说明一下。

 除了PyDll用于直接调用Python C api函数之外,其他的三个主要区别在于

  • 使用的平台;
  • 被加载动态库中函数的调用约定(calling convention);
  • 库中函数假定的默认返回值。

 也就是平台和被加载动态库中函数的调用约定决定了我们应该使用哪种方式加载动态库。

本例中我们在windows平台上使用的是CDLL而不是WinDll,原因是msvcrt.dll中函数调用约定是C/C++默认的调用约定__cdecl。

而WinDll虽然是可以应用于windows平台上,但是其只能加载标准函数调用约定为__stdcall的动态库。因此这里只能使用CDLL方式。

可以将上面的CDLL换成WinDll看一下会不会有问题。这里应该能够对函数调用理解的更加深刻一些了,同时也回答了上面第一小节中我们提问的问题4。

3.2 跨语言类型转换

 这里主要针对第一节提出的问题3。

我们是在python中调用C的函数,函数实参是python类型的变量,函数形参则是C类型的变量,显然我们将python类型的变量直接赋值给C类型的变量肯定会有问题的。

因此这里需要两种语言变量类型之间有一一转换的必要。这里仅仅列出部分对应关系(由于博客园的表格显示会有问题,因此这样列出,请见谅):

Python type        Ctypes type          C type

int/long             c_int             int

float             c_double           double

string or None        c_char_p           char * (NUL terminated)

unicode or None       c_wchar_p          wchar_t * (NUL terminated)

 通过Ctypes type中提供类型,我们建立了一种python类型到c类型的一种转换关系。

在看一下上面的例子Example 1。在调用C的函数时,我们传给C函数的实参需要经过Ctypes转换成C类型之后才能正确的调用C的函数。

3.3 设定C函数的返回类型

看一下上面的例子Example 2.

libc.sin.restype = ctypes.c_double

我们通过restype的方式指定了C(math 模块)函数sin的返回类型为double,对应到python即为float。显然函数的返回类型在DLL中是无法获取的。

开发人员也只能从库的说明文档或者头文件中获取到函数的声明,进而指定函数返回值的类型。

double sin (double x);
float sin (float x);
long double sin (long double x);
double sin (T x);           // additional overloads for integral types

上面是C++11中cmath中sin函数的声明。这里几个sin函数是C++中的函数重载。

libc.sin(ctypes.c_double(30 * 3.14 / 180))

由于调用之前指定了sin函数的返回类型ctypes.c_double,因此sin的调用结果在python中最终会转换为float类型。

3.4 假定的函数返回类型

由于我们在动态库中获取的函数并不知道其返回类型,因为我们只得到了函数的实现,并没有函数的声明。

在没有指定库函数返回类型的情况下,ctypes.CDLL和ctyps.WinDll均假定函数返回类型是int,而ctypes.oleDll则假定函数返回值是Windows HRESULT。

那如果函数实际的返回值不是int,便会按照int返回值处理。如果返回类型能转为int类型是可以的,如果不支持那函数调用的结果会是一个莫名其妙的数字。

time_t time (time_t* timer);

  上面的例子Example 4则默认将C类型time_t转为了python 的int类型,结果是正确的。

对于Example 3中我们不仅要指定函数pow的返回类型,还要转换函数的实参(这里很容易疏忽)。

因此在调用动态库之前一定要看下函数声明,指定函数返回类型。

到这里很容易想到可以指定函数的返回值类型,那能不能指定函数形参的类型呢?答案是肯定的,argtypes 。

printf.argtypes = [c_char_p, c_char_p, c_int, c_double]

3.5 可变string buffer

 上面的例子Exapmle 5中我们调用了C中的一个字符串拷贝函数strcpy,这里函数的返回值和被拷贝的对象均为正确的。

但是这里是故意这样写的,因为这里会有一个问题。

如果res = 'Hello'改为res = 'He'和res = 'HelloWorld',那么实际上res的结果会是‘Wo’和'World\x00orld'。

str_buf = ctypes.create_string_buffer(10)
print ctypes.sizeof(str_buf)                       # 10
print repr(str_buf.raw)                            # '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
str_buf.raw = 'Cnblogs'
print repr(str_buf.raw)                            # 'Cnblogs\x00\x00\x00'
print repr(str_buf.value)                          # 'Cnblogs'

这里我们可以通过ctypes.create_string_buffer来指定一个字符串缓存区。

使用string buffer改写Example 5:

libc.strcpy.restype = ctypes.c_char_p
res = ctypes.create_string_buffer(len('World') + 1)
print libc.strcpy(res, ctypes.c_char_p('World'))
print repr(res.raw), res.value                     # 'World\x00' 'World'

注意上面的res的类型是c_char_Array_xxx。这里只是为了介绍string buffer,实际上不会这么用。

3.6 小节

这里简单的介绍了一下ctypes如何和动态库打交道。限于篇幅还有指针,引用类型和数组等的传递,以及自定义类型等没有介绍。但是这一小结应该能对python引用动态库过程有一个大致的认识。

更加详细信息可以参考官网:ctypes

4. 自定义DLL文件导入

为了更好的理解python调用DLL的过程,有必要了解一下DLL的定义文件。

4.1 C/C++引用DLL

首先,作为对比我们看一下C/C++如何引用DLL文件的。下面的文件是 ./Project2/Source2.cpp

工程配置为:Conguration Properties>General>Configuration Types: Dynamic Library (.dll)

输出路径:./Debug/Project2.dll

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 
 5 #ifdef _MSC_VER
 6 #define DLL_EXPORT extern "C" __declspec( dllexport )
 7 #else
 8 #define DLL_EXPORT
 9 #endif
10 
11 __declspec(dllexport) char* gl = "gl_str";
12 
13 DLL_EXPORT void __stdcall hello_world(void) {
14     printf("%s Hello world!\n", gl);
15 }
16 
17 DLL_EXPORT int my_add(int a, int b) {
18     printf("calling my_add@int func\n");
19     return a + b;
20 }
21 
22 //DLL_EXPORT double my_add(double a, double b) {
23 //    printf("calling my_add@double func\n");
24 //    return a + b;
25 //}
26 
27 DLL_EXPORT int my_mod(int m, int n) {
28     return m % n;
29 }
30 
31 DLL_EXPORT bool is_equal(double a, double b) {
32     return fabs(a - b) < 1e-3;
33 }
34 
35 DLL_EXPORT void my_swap(int *p, int *q) {
36     int tmp = *p;
37     *p = *q;
38     *q = tmp;
39 }
40 
41 inline void swap_char(char *p, char *q) {
42     char tmp = *p;
43     *p = *q;
44     *q = tmp;
45 }
46 
47 DLL_EXPORT void reverse_string(char *const p) {
48     if (p != nullptr) {
49         for (int i = 0, j = strlen(p) - 1; i < j; ++i, --j)
50             swap_char(p + i, p + j);
51             //swap_char(&p[i], &p[j]);
52     }
53 }

 下面的文件是 ./Project1/Source1.cpp

工程配置为:Conguration Properties>General>Configuration Types: Application (.exe)

输出路径:./Debug/Project1.exe

 1 #include "stdio.h"
 2 #include "cstdlib"
 3 #pragma comment(lib, "../Debug/Project2.lib")
 4 
 5 #ifdef _MSC_VER
 6 #define DLL_IMPORT extern "C" __declspec( dllimport )
 7 #else
 8 #define DLL_IMPORT
 9 #endif
10 
11 DLL_IMPORT void __stdcall hello_world(void);
12 DLL_IMPORT int my_add(int, int);
13 DLL_IMPORT int my_mod(int, int);
14 DLL_IMPORT bool is_equal(double, double);
15 DLL_IMPORT void my_swap(int*, int*); 
16 DLL_IMPORT void reverse_string(char* const);
17 
18 __declspec(dllimport) char* gl;
19 
20 int main() {
21     int a = 0, b = 1;
22     char s[] = "123456";
23     hello_world();
24     my_swap(&a, &b);
25     reverse_string(s);
26     printf("DLL str gl: %s \n", gl);
27     printf("DLL func my_add: %d\n", my_add(1,2));
28     printf("DLL func my_mod: %d\n", my_mod(9, 8));
29     printf("DLL func my_comp: %s\n", is_equal(1, 1.0001) ? "true":"false");
30     printf("DLL func my_swap: (%d, %d)\n", a, b);
31     printf("DLL func reverse_string: %s\n", s);
32     system("pause");
33 }

 上面的这个例子已经清楚的展示了C/C++如何导出和引用DLL文件。有以下几点需要注意:

  1. 上面#pragma comment(lib, "../Debug/Project2.lib")中引用的是生成Project2.dll过程中产生的导出库,并非静态库。
  2. __declspec声明只在Windows平台用,若是引用静态库,则不需要__declspec声明。
  3. 不管动态库还是静态库,除了用#pragma comment引用lib文件外,还可以在Conguration Properties>Linker>Input>Additional Dependencies中添加lib文件。
  4. 上面例子中我们导出和引用均声明了extern "C",表示让编译器以C的方式编译和链接文件。意味着导出的函数不支持重载,且函数调用约定为C和C++的默认调用约定__cdecl。
  5. DLL_EXPORT void __stdcall hello_world(void)指定了函数使用__stdcall的Calling Convention,该方式声明优先于编译器默认的__cdecl方式。
  6. 不同的调用约定不仅会影响实际的函数调用过程,还会影响编译输出函数的命名。比如函数hello_world以__cdecl方式和__stdcall方式输出到DLL中的函数分别为hello_world和_hello_world@0。

4.2 python引用DLL

先使用VS自带的dumpbin工具看一下Project2.dll文件部分内容:

dumpbin -exports "./Debug/project2.dll"

ordinal hint RVA      name

1    0 00018000 ?gl@@3PADA
2    1 00011217 _hello_world@0
3    2 00011046 is_equal
4    3 0001109B my_add
5    4 000112D0 my_mod
6    5 00011005 my_swap
7    6 0001118B reverse_string

 话不多说,先上代码:

 1 import ctypes, platform, time
 2 if platform.system() == 'Windows':
 3     my_lib = ctypes.cdll.LoadLibrary(r'.\Debug\Project2.dll')
 4     # my_lib = ctypes.CDLL(r'.\Debug\Project2.dll')
 5 elif platform.system() == 'Linux':
 6     my_lib = ctypes.cdll.LoadLibrary('libc.so.6')
 7 
 8 # [C++] __declspec(dllexport) char* gl = "gl_str";
 9 print ctypes.c_char_p.in_dll(my_lib, '?gl@@3PADA').value    # result: gl_str
10 
11 # [C++] DLL_IMPORT void __stdcall hello_world(void);
12 getattr(my_lib, '_hello_world@0')()    # result: gl_str Hello world!
13 
14 # [C++] DLL_IMPORT int my_add(int, int);
15 print my_lib.my_add(1, 2)         # result: 3                 
16 
17 # [C++] DLL_IMPORT int my_mod(int, int);
18 print my_lib.my_mod(123, 200)    # result: 123
19 
20 # [C++] DLL_IMPORT void my_swap(int*, int*); 
21 a, b = 111, 222
22 pa, pb = ctypes.pointer(ctypes.c_int(a)), ctypes.pointer(ctypes.c_int(b))
23 my_lib.my_swap(pa, pb)
24 print pa.contents.value, pb.contents.value  # result: 222, 111
25 print a, b    # result: 111, 222
26 
27 # [C++] DLL_IMPORT bool is_equal(double, double);
28 my_lib.is_equal.restype = ctypes.c_bool
29 my_lib.is_equal.argtypes = [ctypes.c_double, ctypes.c_double]
30 # print my_lib.is_equal(ctypes.c_double(1.0), ctypes.c_double(1.0001))
31 print my_lib.is_equal(1.0, 1.0001)    # result: True
32 print my_lib.is_equal(1.0, 1.0100)    # result: False
33 
34 # [C++] DLL_IMPORT void reverse_string(char *const);
35 s = "123456"
36 ps = ctypes.pointer(ctypes.c_char_p(s))
37 print ps.contents    # result: c_char_p('123456')
38 my_lib.reverse_string(ctypes.c_char_p(s))
39 print ps.contents, s  # result: c_char_p('654321') 654321

 上面的代码加上注释和结果已经很详细的说明了python引用DLL的过程,限于篇幅,这里就不在赘述。

有一点需要强调,我们使用__stdcall方式声明函数hello_world方式,并且用CDLL方式引入。导致无法直接用lib.func_name的方式访问函数hello_world。

如果想要使用my_lib.hello_world的方式调用该函数,只需要使用windll的方式引入DLL,或者使用默认的__cdecl方式声明hello_world。

5 总结

先来看一下开始提问的问题,部分问题已经在文中说明。

1.python可不可以引用静态库?

首先,静态库是会在链接的过程组装到可执行文件中的,静态库是C/C++代码。

其次,python是一种解释性语言,非静态语言,不需要编译链接。

最后,官网好像没有提供对应的对接模块。

5.如果调用DLL库的过程中出现问题,是我们调用的问题还是库本身的问题?应该怎样快速排查和定位问题?

python中怎么定位问题这个不多说。

DLL中的问题可以使用VS的attach to process功能,将VS Attach 到当前运行的python程序,然后调用到DLL,加断点。

6.有没有什么现有的框架能够帮我们处理python中引用第三方库的问题呢?

常用的有ctypes,swig, cython, boost.python等

7.对于自定义的类型(class 和 struct)是否能在python中被引用。

至少ctypes中没有相关的操作。

其实也没必要,因为不仅python中没有对应的类型,而且完全可以通过将自定义的类或者结构体封装在DLL输出的函数接口中进行访问等操作。

总结:

本文使用python自带的库ctypes介绍了如果引用动态库DLL文件,相对于其他的第三方库,这是一个相对比较低级的DLL包装库。但正是因为这样我们才能看清楚调用DLL过程的一些细节。使用ctypes过程遇到的每一个错误都可能是一个我们未知的知识点,因此建议先熟悉该库,尽可能深入的了解一下python调用动态库的过程。其他的库原理是一样的,只不过进行了更高级的封装而已。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python使用Ctypes与C/C++

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python使用Ctypes与C/C++

项目中可能会经常用到第三方库,主要是出于程序效率考虑和节约开发时间避免重复造轮子。无论第三方库开源与否,编程语言是否与当前项目一致,我们最终的目的是在当前编程环境中调用库中的方法并得到结果或者借助库中的模块实现某种功能。这个过程会牵涉到很多
2023-01-30

Python与C之间的相互调用(Python C API及Python ctypes库)

问题,需要实现全局快捷键,但是是事实上Qt并没有对全局快捷键提供支持,那么用Qt的话就只能通过Win32Api来完成了,而我,用的是PyQt,还需要用Python来调用win32 API,事实上,都没有什么难的。因为Python如此的流行,
2023-06-05

python使用ctypes模块下的wi

原因:python是64位的python,而windll.LoadLibrary只能由32位的python使用  参考: 64位Python调用32位DLL方法(一)解决方法:使用32位的python(切记版本不要太新,本人一开始使用最新的
2023-01-30

Python 扩展使用 C/C++ 给

本文来自作者 gashero 在 GitChat 上分享「Python 的 C 扩展开发惯例」,「阅读原文」查看交流实录「文末高能」编辑 | 嘉仔目录1   简介    1.1   Python扩展模块的用途和优点    1.2   设计扩
2023-01-31

【C/C++】c++多进程与hiredis的浅使用

#include #include #include #include #include int main(){
2023-06-03

如何实现 C/C++ 与 Python

属于混合编程的问题。较全面的介绍一下,不仅限于题主提出的问题。以下讨论中,Python指它的标准实现,即CPython(虽然不是很严格)本文分4个部分1. C/C++ 调用 Python (基础篇)— 仅讨论Python官方提供的实现方式
2023-01-31

【C/C++与MySql的连接及使用详解】

文章目录 概要:本期主要讲解C或者C++怎么在程序中连接MySql数据库。主要步骤一、MySql的链接库二、项目环境配置三、项目内调用MySql类进行数据库操作1.准备工作2.连接数据库3.数据库建表4.向表中插入数据5.查询表中数
2023-08-20

如何使用 C++ 与 Python 实现二分查找

与递归方法产生的 O(logn) 相比,迭代方法的空间复杂度为 O(1) 。那么,如何使用 C、C++ 和 Python 中的迭代方法实现二分查找算法呢?
C++Python算法2024-12-01

深刻揭示Python 与C/C++互动

按:陈儒先生的《Python源码剖析--深度探索动态语言核心技术》已经上架销售,欢迎大家评论、样章试读和购买。点击下图免费试读:海猫MSN上问我:能否帮着写一篇《Python源码剖析》的书评?他给我发这条信息时,我正在聚精会神地敲一段超无聊
2023-01-31

C++BoostArray与Unordered使用介绍

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-13

C++ ROS与boost:bind()使用详解

boost::bind是标准库函数std::bind1st和std::bind2nd的一种泛化形式,其可以支持函数对象、函数、函数指针、成员函数指针,并且绑定任意参数到某个指定值上或者将输入参数传入任意位置,本文重点介绍下C++ ROS与boost:bind(),感兴趣的朋友跟随小编一起看看吧
2023-01-10

Python C API 使用详解(二)

简介介绍Python C API中的列表、元组、字典的使用,详细的进行了API中方法的介绍。Python List APIList API 简单介绍int PyList_Check(PyObject *p) 判断是否是一个Python
2023-01-31

Python和C++使用哪个好

本篇内容主要讲解“Python和C++使用哪个好”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python和C++使用哪个好”吧!Python是解释型语言,而C++不是C++的工作方式是,首先将
2023-06-16

C++Boost.Range与Adapters库使用详解

这篇文章主要介绍了C++Boost.Range与Adapters库使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2022-11-13

c++类怎么定义与使用

在C++中,可以使用class关键字来定义一个类。类定义包括类的成员变量和成员函数。以下是一个简单的C++类的定义和使用的示例:```cpp// 定义一个类class MyClass {public:// 成员变量int myInt;//
2023-09-26

C++ Boost Array与Unordered怎么使用

这篇文章主要介绍“C++ Boost Array与Unordered怎么使用”,在日常操作中,相信很多人在C++ Boost Array与Unordered怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
2023-07-04

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录