当前位置: 首页 > 面试题库 >

在没有CGo的情况下从Go调用COM对象方法

皇甫飞飙
2023-03-14
问题内容

我在Go中创建了Direct3D9包装器,该包装器使用CGo与C中的COM对象进行接口。

我想摆脱Windows下对C编译器的依赖,因此用户不必安装MinGW或Cygwin即可使用Go中的DirectX。

问题在于d3d9.dll不会公开C函数,而是使用COM。加载DLL(带有syscall.LoadLibrary("d3d9.dll"))后,可以直接调用的唯一函数是Direct3DCreate9。这将返回一个COM对象,该对象将所有功能公开为方法。

如何在没有CGo的纯Go中调用DLL中的COM对象方法?

我知道Go-OLE库,该库声明它在没有CGo的情况下调用COM接口,但是从源头上我看不到如何为Direct3D9做同样的事情。一个仅包含相关部分的简单示例将大有帮助。


问题答案:

我问go-ole的家伙,就像@kostix建议的那样。

解决方法如下:

d3d9通常没有COM vtbl。例如,它没有IDispatch接口。因此,您不能对d3d9使用go-ole。但是您可以通过编写所有接口来实现。

package main

import (
    "fmt"
    "log"
    "syscall"
    "unsafe"
)

const (
    D3D9_SDK_VERSION = 32
)

var (
    libd3d9             = syscall.NewLazyDLL("d3d9.dll")
    procDirect3DCreate9 = libd3d9.NewProc("Direct3DCreate9")
)

type IDirect3D struct {
    lpVtbl *IDirect3DVtbl
}

type IDirect3DVtbl struct {
    QueryInterface uintptr
    AddRef         uintptr
    Release        uintptr

    RegisterSoftwareDevice      uintptr
    GetAdapterCount             uintptr
    GetAdapterIdentifier        uintptr
    GetAdapterModeCount         uintptr
    EnumAdapterModes            uintptr
    GetAdapterDisplayMode       uintptr
    CheckDeviceType             uintptr
    CheckDeviceFormat           uintptr
    CheckDeviceMultiSampleType  uintptr
    CheckDepthStencilMatch      uintptr
    CheckDeviceFormatConversion uintptr
    GetDeviceCaps               uintptr
    GetAdapterMonitor           uintptr
    CreateDevice                uintptr
}

func (v *IDirect3D) AddRef() int32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.AddRef,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return int32(ret)
}

func (v *IDirect3D) Release() int32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.Release,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return int32(ret)
}

func (v *IDirect3D) GetAdapterCount() uint32 {
    ret, _, _ := syscall.Syscall(
        v.lpVtbl.GetAdapterCount,
        1,
        uintptr(unsafe.Pointer(v)),
        0,
        0)
    return uint32(ret)
}

func main() {
    v, r, err := procDirect3DCreate9.Call(uintptr(D3D9_SDK_VERSION))
    if r != 0 && err != nil {
        log.Fatal(err)
    }
    d3d := *((**IDirect3D)(unsafe.Pointer(&v)))

    d3d.AddRef()
    defer d3d.Release()

    fmt.Println(d3d.GetAdapterCount())
}

(c)马特恩



 类似资料:
  • 问题内容: 我正试图从这样打电话: 该代码可以正常编译,但是会失败。我不知道为什么我无法得到。有人可以帮我吗? 问题答案: 是输入输出参数。进行呼叫时,必须将其设置为缓冲区()的大小。它的类型也是,所以在Go中使用。Windows 类型是指向的指针(具有)。参见来源。 还返回3个值: 存储返回并打印。完成此操作后,您会更早发现错误: 印刷品: 这意味着更多的数据比什么适合入缓冲区您传递可用- 或者

  • 我需要一个apache/php来识别ffmpeg命令,而不需要指定/usr/local/bin/ffmpeg的完整格式 从命令行调用ffmpeg执行程序通过web从php调用ffmpeg不执行程序通过web从php调用 /usr/local/bin/ffmpeg执行程序 原因:php脚本调用youtube dl(编译程序)并在内部执行ffmpeg 提前感谢-尝试了ffmpeg路径:哪个ffmpeg

  • 问题内容: 这是使用awt包的Java图形的初学者问题。我在网上找到了这段代码来绘制一些简单的图形。 在main方法中,在画布上没有调用paint()。但是我运行了该程序并且它可以工作,那么paint()方法如何运行? 问题答案: 该方法由事件调度线程(EDT)调用,并且基本上不受您的控制。 它的工作方式如下:当 实现 用户界面(以您的情况为例)时,Swing将启动EDT。然后,此EDT线程在后台

  • 所以,我想做的是: 创建水果的对象作为键和它们出现的次数。结束对象如下所示: 所以对于“苹果”来说: 我回顾了一堆帖子和链接,这些帖子和链接让我陷入了一个兔子洞。即便如此,他们中没有一个明确地解决了我所能说出的问题。 这段代码中Number对象保存属性并增加数字时发生了什么? 如何增加JavaScript对象中的值? 如何在JavaScript中使用for…语法获得循环计数器/索引? 遍历对象数组

  • 我看到的所有解决方案都需要使用。但是,我想在Eclipse之外的单个文件上使用CDT解析器。那有什么办法吗?

  • 问题内容: 我有一个模型,当从前端发送请求时,我可以在控制器中使用@Valid进行验证: 但是现在,我还使用不含控制器的Jackson的ObjectMapper创建了一个对象。有没有一种方法可以在ObjectMapper中注册此验证,还是应该只检查setter中的变量? 问题答案: 反序列化后,您可以扩展和验证对象。要注册此bean使用。 具有验证的简单bean反序列化器: 我们可以如下使用它: