Python调用DLL动态链接库——ctypes使用
<p>最近要使用python调用C++编译生成的DLL动态链接库,因此学习了一下ctypes库的基本使用。</p><p><code>ctypes</code>是一个用于Python的外部函数库,它提供C兼容的数据类型,并允许在DLL或共享库中调用函数。</p>
<h2>一、Python调用DLL里面的导出函数</h2>
<h3>1.VS生成dll</h3>
<p>1.1 新建动态链接库项目</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827220920039-1813444907.png" alt="" width="795" height="491"></p>
<p>1.2 在myTest.cpp中输入以下内容:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> myTest.cpp : 定义 DLL 应用程序的导出函数。
</span><span style="color: rgba(0, 128, 0, 1)">//
</span>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stdafx.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">#define</span> DLLEXPORT extern "C" __declspec(dllexport) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">放在 #include "stdafx.h" 之后</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">两数相加</span>
DLLEXPORT <span style="color: rgba(0, 0, 255, 1)">int</span> sum(<span style="color: rgba(0, 0, 255, 1)">int</span> a, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> b) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> a +<span style="color: rgba(0, 0, 0, 1)"> b;
}</span></pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)">注意:导出函数前面要加 extern "C" __declspec(dllexport) ,这是因为ctypes只能调用C函数。如果不用extern "C",构建后的动态链接库没有这些函数的符号表。采用C++的工程,导出的接口需要extern "C",这样python中才能识别导出的函数。</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">1.3生成dll动态链接库</span></p>
<p>因为我的python3是64位的,所以VS生成的dll要选择64位的,如下所示:</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827222817695-1658142059.png" alt=""></p>
<p> 点击标题栏的 <span style="color: rgba(0, 128, 0, 1)">生成</span> -> <span style="color: rgba(0, 128, 0, 1)">生成解决方案 </span></p>
<p> <img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827221408574-1766127199.png" alt=""></p>
<p>1.4 查看生成的dll动态链接库</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827222657125-1070703225.png" alt=""></p>
<h3>2.Python导入dll动态链接库</h3>
<p>用python将动态链接库导入,然后调用动态链接库的函数。为此,新建main.py文件,输入如下内容:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> ctypes <span style="color: rgba(0, 0, 255, 1)">import</span> *
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">----------以下四种加载DLL方式皆可—————————</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> pDLL = WinDLL("./myTest.dll")</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> pDll = windll.LoadLibrary("./myTest.dll")</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)"> pDll = cdll.LoadLibrary("./myTest.dll")</span>
pDll = CDLL(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">./myTest.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">调用动态链接库函数</span>
res = pDll.sum(1,2<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">打印返回结果</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(res)</pre>
</div>
<p>运行结果如下所示:</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827223046072-834539309.png" alt=""></p>
<h2> </h2>
<h2>二、Python调用DLL里面的实例方法更新全局变量值</h2>
<h3> 1.VS生成dll</h3>
<p>1.1 添加 mainClass 类,内容如下:</p>
<p>mainClass.h:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">#pragma</span> once
<span style="color: rgba(0, 0, 255, 1)">extern</span> <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> dta;
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> mainClass
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)">:
mainClass();
</span>~<span style="color: rgba(0, 0, 0, 1)">mainClass();
</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> produceData();
};</span></pre>
</div>
<p>mainClass.cpp:</p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stdafx.h</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mainClass.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> dta = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
mainClass::mainClass()
{
}
mainClass::</span>~<span style="color: rgba(0, 0, 0, 1)">mainClass()
{
}
</span><span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> mainClass::produceData() {
dta </span>= <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p> 1.2 更改 myTest.cpp 内容</p>
<p>myTest.cpp:</p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stdafx.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">#define</span> DLLEXPORT extern "C" __declspec(dllexport) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">放在 #include "stdafx.h" 之后</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">mainClass.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回实例方法里面更新数据后的值</span>
DLLEXPORT <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> getRandData() {
mainClass dataClass </span>=<span style="color: rgba(0, 0, 0, 1)"> mainClass();
dataClass.produceData();
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dta;
}</span></pre>
</div>
<p>1.3 生成64位dll</p>
<h3>2.Python导入dll动态链接库</h3>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190827230127838-486215593.png" alt=""></p>
<p>明显可以看出,在C++里设置的全局变量的值已经从0变为10了,说明python可以通过调用dll里面的实例方法来更新全局变量值</p>
<p> </p>
<h2>三、Python_ctypes 指定函数参数类型和返回类型</h2>
<p><span style="color: rgba(255, 0, 0, 1)">前面两个例子C++动态链接库导出函数的返回类型都是int型,而Python 默认函数的参数类型和返回类型为 int 型,所以Python 理所当然的 以为 dll导出函数返回了一个 int 类型的值。<span style="color: rgba(0, 0, 0, 1)">但是如果C++动态链接库导出的函数返回类型不是int型,而是特定类型,就需要指定ctypes的函数返回类型 restype 。同样,通过ctypes给函数传递参数时,参数类型默认为int型,如果不是int型,而是特定类型,就需要指定ctypes的函数形参类型 argtypes 。</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">接下来,我将举一个简单例子来说明一下</span></span></p>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">myTest.cpp:</span></span></p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stdafx.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">#define</span> DLLEXPORT extern "C" __declspec(dllexport) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">放在 #include "stdafx.h" 之后</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><<span style="color: rgba(0, 0, 255, 1)">string</span>> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用string类型 需要包含头文件 <string></span>
<span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span> std; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">string类是一个模板类,位于名字空间std中
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字符串</span>
DLLEXPORT <span style="color: rgba(0, 0, 255, 1)">char</span> *getRandData(<span style="color: rgba(0, 0, 255, 1)">char</span> *<span style="color: rgba(0, 0, 0, 1)">arg) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> arg;
}</span></pre>
</div>
<p>python代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> ctypes <span style="color: rgba(0, 0, 255, 1)">import</span> *<span style="color: rgba(0, 0, 0, 1)">
pDll </span>= CDLL(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">./myTest.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">######### 指定 函数的参数类型 #################</span>
pDll.getRandData.argtypes =<span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">第一个参数</span>
arg1 = c_char_p(bytes(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">utf-8</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">))
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">######### 指定 函数的返回类型 #################</span>
pDll.getRandData.restype =<span style="color: rgba(0, 0, 0, 1)"> c_char_p
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">########## 调用动态链接库函数 ##################</span>
res =<span style="color: rgba(0, 0, 0, 1)"> pDll.getRandData(arg1)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">打印返回结果</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(res.decode()) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回的是utf-8编码的数据,需要解码</span></pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">或者如下形式:</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">from</span> ctypes <span style="color: rgba(0, 0, 255, 1)">import</span> *<span style="color: rgba(0, 0, 0, 1)">
pDll </span>= CDLL(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">./myTest.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">######### 指定 函数的返回类型 #################</span>
pDll.getRandData.restype =<span style="color: rgba(0, 0, 0, 1)"> c_char_p
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">########## 调用动态链接库函数 ##################</span>
res = pDll.getRandData(b<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hello</span><span style="color: rgba(128, 0, 0, 1)">'</span>) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 或者变量.encode()</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">打印返回结果</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(res.decode()) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回的是utf-8编码的数据,需要解码</span></pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">运行结果:</span></span></p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201908/1327126-20190828123417267-1884358107.png" alt=""></p>
<p> </p>
<h2>四、Python_ctypes dll返回数组_结构体</h2>
<p>在ctypes里,可以把数组指针传递给dll,但是我们无法通过dll获取到c++返回的数组指针。由于python中没有对应的数组指针类型,因此,要获取dll返回的数组,我们需要借助结构体。</p>
<p> myTest.cpp:</p>
<div class="cnblogs_code">
<pre>#include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">stdafx.h</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">#define</span> DLLEXPORT extern "C" __declspec(dllexport) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">放在 #include "stdafx.h" 之后</span><span style="color: rgba(0, 0, 0, 1)">
#include </span><<span style="color: rgba(0, 0, 255, 1)">string</span>> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用string类型 需要包含头文件 <string></span>
<span style="color: rgba(0, 0, 255, 1)">using</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span> std; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">string类是一个模板类,位于名字空间std中</span>
<span style="color: rgba(0, 0, 0, 1)">
typedef </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> StructPointerTest
{
</span><span style="color: rgba(0, 0, 255, 1)">char</span> name[<span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> age;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> arr[<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(0, 0, 255, 1)">int</span> arrTwo[<span style="color: rgba(128, 0, 128, 1)">2</span>][<span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">];
}StructTest, </span>*<span style="color: rgba(0, 0, 0, 1)">StructPointer;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">sizeof(StructTest)就是求 struct StructPointerTest 这个结构体占用的字节数
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">malloc(sizeof(StructTest))就是申请 struct StructPointerTest 这个结构体占用字节数大小的空间
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">(StructPointer)malloc(sizeof(StructTest))就是将申请的空间的地址强制转化为 struct StructPointerTest * 指针类型
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">StructPointer p = (StructPointer)malloc(sizeof(StructTest))就是将那个强制转化的地址赋值给 p</span>
StructPointer p = (StructPointer)<span style="color: rgba(0, 0, 255, 1)">malloc</span>(<span style="color: rgba(0, 0, 255, 1)">sizeof</span><span style="color: rgba(0, 0, 0, 1)">(StructTest));
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字符串</span>
DLLEXPORT StructPointer test() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 返回结构体指针</span>
<span style="color: rgba(0, 0, 0, 1)">{
strcpy_s(p</span>->name, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Lakers</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
p</span>->age = <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">;
p</span>->arr[<span style="color: rgba(128, 0, 128, 1)">0</span>] = <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
p</span>->arr[<span style="color: rgba(128, 0, 128, 1)">1</span>] = <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
p</span>->arr[<span style="color: rgba(128, 0, 128, 1)">2</span>] = <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < <span style="color: rgba(128, 0, 128, 1)">2</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> j = <span style="color: rgba(128, 0, 128, 1)">0</span>; j < <span style="color: rgba(128, 0, 128, 1)">3</span>; j++<span style="color: rgba(0, 0, 0, 1)">)
p</span>->arrTwo = i*<span style="color: rgba(128, 0, 128, 1)">10</span>+<span style="color: rgba(0, 0, 0, 1)">j;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> p;
}</span></pre>
</div>
<p> python代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 返回结构体</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> ctypes
path </span>= r<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./myTest.dll</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
dll </span>=<span style="color: rgba(0, 0, 0, 1)"> ctypes.WinDLL(path)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">定义结构体</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> StructPointer(ctypes.Structure):<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">Structure在ctypes中是基于类的结构体</span>
_fields_ = [(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">name</span><span style="color: rgba(128, 0, 0, 1)">"</span>, ctypes.c_char * 20), <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">定义一维数组</span>
(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">age</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, ctypes.c_int),
(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">arr</span><span style="color: rgba(128, 0, 0, 1)">"</span>, ctypes.c_int * 3), <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">定义一维数组</span>
(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">arrTwo</span><span style="color: rgba(128, 0, 0, 1)">"</span>, (ctypes.c_int * 3) * 2)] <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">定义二维数组</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">设置导出函数返回类型</span>
dll.test.restype = ctypes.POINTER(StructPointer)<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> POINTER(StructPointer)表示一个结构体指针</span><span style="color: rgba(0, 128, 0, 1)">
#</span><span style="color: rgba(0, 128, 0, 1)">调用导出函数</span>
p =<span style="color: rgba(0, 0, 0, 1)"> dll.test()
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p.contents.name.decode())<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">p.contents返回要指向点的对象 #返回的字符串是utf-8编码的数据,需要解码</span>
<span style="color: rgba(0, 0, 255, 1)">print</span><span style="color: rgba(0, 0, 0, 1)">(p.contents.age)
</span><span style="color: rgba(0, 0, 255, 1)">print</span>(p.contents.arr) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回一维数组第一个元素</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(p.contents.arr[:]) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回一维数组所有元素</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(p.contents.arrTwo[:]) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回二维数组第一行所有元素</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(p.contents.arrTwo[:]) <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)">返回二维数组第二行所有元素</span></pre>
</div>
<p> 运行结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201909/1327126-20190905144632431-222627218.png" alt=""></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/FHC1994/p/11421229.html
頁:
[1]