在使用Golang绑定库torrent时,如何转换为“alert”类型。

huangapple go评论116阅读模式
英文:

Casting an "alert" type in libtorrent, using Golang bindings

问题

我正在开发一个使用Golang的个人项目,使用libtorrent-go

当我收到类型为"save_resume_data_alert"的警报时,我会捕获它,并且需要按照libtorrent文档中的写法进行类型转换。

  1. ...
  2. save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(a);
  3. ...

但是我真的不知道如何在Golang中进行类型转换!当前的代码如下:

  1. package main
  2. import (
  3. lt "github.com/steeve/libtorrent-go"
  4. "log"
  5. "time"
  6. )
  7. func main() {
  8. randomTorrent := lt.NewAdd_torrent_params()
  9. randomTorrent.SetUrl("PUT A MAGNET LINK HERE")
  10. randomTorrent.SetSave_path(".")
  11. ec := lt.NewError_code()
  12. torrentSession := lt.NewSession()
  13. torrentSession.Set_alert_mask(status_notification + storage_notification)
  14. torrentSession.Listen_on(lt.NewStd_pair_int_int(6900, 6999), ec)
  15. if ec.Value() != 0 {
  16. log.Println(ec.Message())
  17. }
  18. torrentHandle := torrentSession.Add_torrent(randomTorrent, ec)
  19. if ec.Value() != 0 {
  20. log.Println(ec.Message())
  21. }
  22. go func() {
  23. for {
  24. if torrentSession.Wait_for_alert(lt.Seconds(10)).Swigcptr() == 0 {
  25. log.Println("Alert timeout occurred!")
  26. }
  27. alert := torrentSession.Pop_alert()
  28. switch alert.What() {
  29. default:
  30. log.Printf("Alert: %#v", alert.What())
  31. case "metadata_received_alert":
  32. log.Println("Received Metadata!! finally!")
  33. torrentHandle.Save_resume_data()
  34. case "save_resume_data_alert":
  35. log.Println("Wrote Metadata!")
  36. // 需要实际写入resume_data :( 找不到如何写入
  37. case "save_resume_data_failed_alert":
  38. log.Println("Failed Metadata!")
  39. }
  40. }
  41. }()
  42. select {}
  43. }

请注意,我只会翻译代码部分,不会回答关于翻译的问题。

英文:

I am developing a personal project in Golang, using libtorrent-go

When I do receive an alert of type &quot;save_resume_data_alert&quot;, I pick it up and have to CAST it as written in libtorrent documentation

  1. ...
  2. save_resume_data_alert const* rd = alert_cast&lt;save_resume_data_alert&gt;(a);
  3. ...

But i really have not idea how to cast it in golang! Current code:

  1. package main
  2. import (
  3. lt &quot;github.com/steeve/libtorrent-go&quot;
  4. &quot;log&quot;
  5. &quot;time&quot;
  6. )
  7. func main() {
  8. randomTorrent := lt.NewAdd_torrent_params()
  9. randomTorrent.SetUrl(&quot;PUT A MAGNET LINK HERE&quot;)
  10. randomTorrent.SetSave_path(&quot;.&quot;)
  11. ec := lt.NewError_code()
  12. torrentSession := lt.NewSession()
  13. torrentSession.Set_alert_mask(status_notification + storage_notification)
  14. torrentSession.Listen_on(lt.NewStd_pair_int_int(6900, 6999), ec)
  15. if ec.Value() != 0 {
  16. log.Println(ec.Message())
  17. }
  18. torrentHandle := torrentSession.Add_torrent(randomTorrent, ec)
  19. if ec.Value() != 0 {
  20. log.Println(ec.Message())
  21. }
  22. go func() {
  23. for {
  24. if torrentSession.Wait_for_alert(lt.Seconds(10)).Swigcptr() == 0 {
  25. log.Println(&quot;Alert timeout occurred!&quot;)
  26. }
  27. alert := torrentSession.Pop_alert()
  28. switch alert.What() {
  29. default:
  30. log.Printf(&quot;Alert: %#v&quot;, alert.What())
  31. case &quot;metadata_received_alert&quot;:
  32. log.Println(&quot;Received Metadata!! finally!&quot;)
  33. torrentHandle.Save_resume_data()
  34. case &quot;save_resume_data_alert&quot;:
  35. log.Println(&quot;Wrote Metadata!&quot;)
  36. // need to actually write the resume_data :( can&#39;t find how
  37. case &quot;save_resume_data_failed_alert&quot;:
  38. log.Println(&quot;Failed Metadata!&quot;)
  39. }
  40. }
  41. }()
  42. select {}
  43. }

答案1

得分: 1

如上所述,libtorrent-go的开发者回答了我,所以我将这个答案转发出来,以备后用。

使用SWIG库在Golang中进行C++结构的转换在SWIG-Golang文档中有详细说明。
特别是在以下语句中:

> 给定接口类型的值,Go代码可以通过调用Swigcptr方法来检索C++类型的指针。
> 这将返回一个SwigcptrClassName类型的值,它只是一个uintptr的别名。
> 可以使用Go类型转换将此值转换为不同的C++类型,但请注意,此转换不会进行类型检查,
> 并且本质上等同于reinterpret_cast。这只应该用于非常特殊的情况,例如C++中使用dynamic_cast的情况。

在我上面发布的那段代码中,为了使其工作,需要进行以下操作:

  1. case "save_resume_data_alert":
  2. log.Println("Wrote Metadata!")
  3. // 需要实际写入resume_data :( 找不到如何写入
  4. SaveRDAlert := lt.SwigcptrSave_resume_data_alert(alert.Swigcptr())
  5. log.Printf("Resume Data: %#v", SaveRDAlert.GetResume_data())
英文:

As stated above, libtorrent-go developer answered me, so I am forwarding the answer for posterity reasons.

Casting C++ structures in Golang using SWIG library is documented in SWIG-Golang documentation.
In particular in this statement:

> Given a value of the interface type, Go code can retrieve the pointer
> to the C++ type by calling the Swigcptr method. This will return a
> value of type SwigcptrClassName, which is just a name for uintptr. A
> Go type conversion can be used to convert this value to a different
> C++ type, but note that this conversion will not be type checked and
> is essentially equivalent to reinterpret_cast. This should only be
> used for very special cases, such as where C++ would use a
> dynamic_cast.

In that particular piece of code I posted above, the following was necessary to make it work:

  1. case &quot;save_resume_data_alert&quot;:
  2. log.Println(&quot;Wrote Metadata!&quot;)
  3. // need to actually write the resume_data :( can&#39;t find how
  4. SaveRDAlert := lt.SwigcptrSave_resume_data_alert(alert.Swigcptr())
  5. log.Printf(&quot;Resume Data: %#v&quot;, SaveRDAlert.GetResume_data())

huangapple
  • 本文由 发表于 2014年12月17日 19:35:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/27524688.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定