Heim > Backend-Entwicklung > Golang > [Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

Freigeben: 2023-07-20 16:32:25
nach vorne
751 Leute haben es durchsucht
Im vorherigen Artikel haben wir den Go-Code erfolgreich über Python aufgerufen und die intensive Berechnung an Go übergeben. Obwohl die Berechnung sehr schnell war, scheint es etwas überraschend, nicht das, was wir uns vorgestellt haben .

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


/2 Was ist der Grund für den Rückgabewertfehler? /

Im letzten Artikel schienen wir alle ein Bild vergessen zu haben.

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


Die .go-Datei gehört zu Go. Nicht viel zu sagen, .so ist die Datei, die Python Go nennt. ? ? Es scheint, dass es keinen Sinn für die Existenz dieser .h-Datei gibt. Es ist ein Eins-zu-Eins-Parameter, der den Go-Code in C-Code umwandelt in C konvertiert ist der GoInt-Typ. Was bedeutet dieser Typ konkret? ? ? Schauen Sie noch einmal.

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

Aus dem Obigen können Sie wahrscheinlich herausfinden, dass GoInt tatsächlich GoInt64 ist und der Typ von GoInt64 ein Long-Long-Typ ist. Ist das ein Witz? ? ?

Wenn wir die .so-Datei in Python aufrufen, verwenden wir tatsächlich <code style="font-family: var(--monospace);vertical-align: initial;border-width: 1px;border-style: solid;border-color: rgb(231, 234, 237);background-color: rgb(243, 244, 244);border-radius: 3px;padding-right: 2px;padding-left: 2px;font-size: 0.9em;"><span style="font-size: 18px;">ctypes</span>ctypes Modul, dieses hat eine entsprechende Tabelle. ??

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

longintc_ulongintschweben
ctypes-Typ C-Typ Python-Typ
c_bool _Bool bool (1)
c_char char c_byte char
int c_ubyte unsigned char int
c_short short int
c_ushort unsigned kurz int
c_int int
unsigned long int
c_longlong __int64 oder long int
c_ulonglong unsigned  __int64 oder unsigned long long oder Py_ssize_t
c_float float
c_double double float
c_longdouble long double float
c_char_p char * (NUL  terminiert ) bytes-Objekt  oder None
c_wchar_p wchar_t * (NUL terminiert) string oder None
c_void_p void * int oder None


    根据上述表格我们可以发现,在C中的long long类型对应的ctype类型是c_longlong。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


    所以我们需要在Python将.so中的返回值改一下,不能使用系统默认的了。代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件
    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000000)  # 调用Go生成的.so文件里面的run函数

    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应
    endTime = time.time()
    print("耗时:", endTime - beginTime)
Nach dem Login kopieren


再次执行:

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

可以看到,这次Python执行的结果和Go执行结果就一个样了。继续,换个数字试试看。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

基本可以确定,这次是没问题了。


/4 如果返回的是字符串呢?/

Go代码

package main

import (
  "C" //C必须导入
  "fmt"
)

//export run
func run(n int) int{
  /*
    必须要export 函数名
    //是注释的意思,相当于Python中的 #
    我也是第一次见注释还有作用
  */
  sum := 0
  for i := 0; i < n; i++ {
    sum += i
  }
  fmt.Println("我是Go代码,我跑完了,我的结果是:",sum)
  return sum
}

//export speak
func speak(n int) string{

  return "OMG 996好累呀,难得休息一天,好好休息"
}
func main() {
  //main函数中什么都不要写,和包名main要对应
}
Nach dem Login kopieren


下面一起来理解.h文件。编译之后打开.h文件如下图所示:

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


可以看到,在extern的函数成了两个,但是他的返回值是GoString,继续找。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


可以发现,其实GoString就是_GoString_,继续找。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

这次是一个结构体,里面其实是两个值,不在是单独的long long了,那Python中的继承类也要改一下了。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern


下面基本同上。

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

完整代码如下:

from ctypes import *
import time

class StructPointer(Structure):
    # 根据查表,C中的long long,对应的ctypes 是 c_longlong
    # _fields_必须是[](列表)类型,里面写对应的类型,固定格式
    _fields_ = [("p", c_longlong,),]

class StrPointer(Structure):
    # typedef struct { const char *p; ptrdiff_t n; } _GoString_;
    # ptrdiff_t == long long
    _fields_ = [("p", c_char_p), ("n", c_longlong)]

if __name__ == &#39;__main__&#39;:
    beginTime = time.time()
    s = CDLL("s1.so")  # 加载s1.so文件

    s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式
    result = s.run(100000798)  # 调用Go生成的.so文件里面的run函数
    print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应

    s.speak.restype = StrPointer
    speakStr = s.speak()
    # 返回的是字节类型,需要转字符串,返回的内容在.p中,.n是切的长度,后面会跟一些介绍,不需要
    speakStr = str(speakStr.p[:speakStr.n], encoding="utf-8")
    print("speak:",speakStr)

    endTime = time.time()
    print("耗时:", endTime - beginTime)
Nach dem Login kopieren


结果:

[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern

    可以看到,调用Go代码成功的拿到了正确的字符串返回值,如果没有 .restype = StrPointer拿到的会是什么呢?拿到会和原来的一样,一堆数字,这里就不举栗子了。


/5 小结/

    至此,基本上在Python调用Go代码上的大坑都解决了,最复杂的是返回字符串类型,查了很多相关资料才解决。

    关于返回其他类型的Python的class怎么写,我相信已经难为不到你们了,最复杂的都解决了,最简单的还不会吗?(除字符串类型以外其他_fields_都是一个字段的)

    我相信各位小伙伴学习能力还是很强的,人生苦短,Python当歌,加油,奥利给!

Das obige ist der detaillierte Inhalt von[Fortgeschritten] Python+Go – Lassen Sie uns einen anderen Weg finden, die Rechenleistung zu verbessern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:Go语言进阶学习
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage