杭州陈奕迅 發表於 2019-8-27 23:04:00

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)">注意:导出函数前面要加&nbsp;&nbsp;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>&nbsp;点击标题栏的 <span style="color: rgba(0, 128, 0, 1)">生成</span> -&gt; <span style="color: rgba(0, 128, 0, 1)">生成解决方案&nbsp;</span></p>
<p>&nbsp;<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>&nbsp;</h2>
<h2>二、Python调用DLL里面的实例方法更新全局变量值</h2>
<h3>&nbsp;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>&nbsp;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>&nbsp;</p>
<h2>三、Python_ctypes 指定函数参数类型和返回类型</h2>
<p><span style="color: rgba(255, 0, 0, 1)">前面两个例子C++动态链接库导出函数的返回类型都是int型,而Python 默认函数的参数类型和返回类型为 int 型,所以Python&nbsp;理所当然的 以为 dll导出函数返回了一个 int 类型的值。<span style="color: rgba(0, 0, 0, 1)">但是如果C++动态链接库导出的函数返回类型不是int型,而是特定类型,就需要指定ctypes的函数返回类型 restype 。同样,通过ctypes给函数传递参数时,参数类型默认为int型,如果不是int型,而是特定类型,就需要指定ctypes的函数形参类型&nbsp;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>&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用string类型 需要包含头文件 &lt;string&gt;</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>&nbsp;</p>
<h2>四、Python_ctypes dll返回数组_结构体</h2>
<p>在ctypes里,可以把数组指针传递给dll,但是我们无法通过dll获取到c++返回的数组指针。由于python中没有对应的数组指针类型,因此,要获取dll返回的数组,我们需要借助结构体。</p>
<p>&nbsp;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>&lt;<span style="color: rgba(0, 0, 255, 1)">string</span>&gt;    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用string类型 需要包含头文件 &lt;string&gt;</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>-&gt;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>-&gt;age = <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">;
    p</span>-&gt;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>-&gt;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>-&gt;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 &lt; <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 &lt; <span style="color: rgba(128, 0, 128, 1)">3</span>; j++<span style="color: rgba(0, 0, 0, 1)">)
            p</span>-&gt;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>&nbsp;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>&nbsp;运行结果:</p>
<p><img src="https://img2018.cnblogs.com/blog/1327126/201909/1327126-20190905144632431-222627218.png" alt=""></p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/FHC1994/p/11421229.html
頁: [1]
查看完整版本: Python调用DLL动态链接库——ctypes使用