- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个关于虚拟表的问题。
我所知道的虚表是可以找到的函数地址数组多态对象调用虚函数时的函数地址。
但是在directx中,有人提到dx vtable就是d3d9.dll的表的导入函数地址数组。
为什么他们调用导入函数地址数组到directx vtable?它似乎与 vtable 无关。
我的知识有误吗?我可以详细了解 vtable 吗?谢谢!
最佳答案
从 DLL 导出 COM 对象时,通常有两个部分在起作用。首先是“工厂”。工厂可以是从 DLL 导出的标准 C 可调用函数(Direct3D 就是这种情况),或者是在系统注册表中注册的类,在这种情况下,您将使用 CoCreateInstance
创建 COM接口(interface)实例。第一个示例是创建 Direct3D 设备:
ID3D11Device* d3dDevice = nullptr;
hr = D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
0,
0,
nullptr,
0,
D3D11_SDK_VERSION,
&d3dDevice,
nullptr,
nullptr);
在此调用之后,d3dDevice
接口(interface)指向分配的 COM 接口(interface)对象。包含 D3D11CreateDevice
的 DLL 必须隐式链接到调用程序——或者您可以使用 LoadLibrary
进行显式链接,在这种情况下您可以使用指向函数 D3D11CreateDevice
的作用大致相同。这是从 DLL 的“导入表”派生的。
第二个示例是您在使用 Windows 图像处理组件 (WIC) 时执行的操作:
IWICImagingFactory* factory = nullptr;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
&factory);
这让 COM 系统在注册表中查找类 GUID,加载引用的 DLL,然后调用其中的工厂方法来创建一个返回给您的 COM 接口(interface)对象。
在这两种情况下,接口(interface)指向的实际内容都是以下形式:
typedef struct IUnknownVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);
END_INTERFACE
} IUnknownVtbl;
它旨在准确地映射到 virtual
的 Visual C++ 实现:
MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
IUnknown
{
public:
BEGIN_INTERFACE
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
END_INTERFACE
};
COM 并没有真正的继承概念,但是 ID3D11Device1
使用来自 ID3D1Device
的 C++ 公共(public)继承还是很方便的,因为语言类型具有没有声明数据成员。接口(interface)的 COM“继承”实际上只是方法的串联,如果您查看 header 中的 C 定义,就会看到这些方法:
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("cc86fabe-da55-401d-85e7-e3c9de2877e9")
ID3D11BlendState1 : public ID3D11BlendState
{
public:
virtual void STDMETHODCALLTYPE GetDesc1(
/* [annotation] */
_Out_ D3D11_BLEND_DESC1 *pDesc) = 0;
};
#else /* C style interface */
typedef struct ID3D11BlendState1Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )( /* ... */ );
ULONG ( STDMETHODCALLTYPE *AddRef )( ID3D11BlendState1 * This);
ULONG ( STDMETHODCALLTYPE *Release )( ID3D11BlendState1 * This);
void ( STDMETHODCALLTYPE *GetDevice )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( /* ... */ );
void ( STDMETHODCALLTYPE *GetDesc )(
ID3D11BlendState1 * This,
/* [annotation] */
_Out_ D3D11_BLEND_DESC *pDesc);
void ( STDMETHODCALLTYPE *GetDesc1 )(
ID3D11BlendState1 * This,
/* [annotation] */
_Out_ D3D11_BLEND_DESC1 *pDesc);
END_INTERFACE
} ID3D11BlendState1Vtbl;
#endif
It's important to note this only works for the case of pure virtual (i.e. abstract) C++ classes with no data members and only virtual methods using public inheritance (i.e. interfaces). Constructors and destructors are ignored as COM life-time is managed through reference-counting via
IUnknown
.
方法的调用签名也将指向 COM 对象的指针作为映射到 this
的 C++ 调用约定的第一个参数。
COM 接口(interface)因此被设计为像 C++ 虚拟方法一样工作,因此您可以使用 C++ 语法调用它们,但它们根本不一定是 C++ 类对象。
从 IUnknown
COM 中有一种已知的标准方法来获取特定接口(interface),即 QueryInterface
。 Direct3D 工厂函数也为您处理这件事,并且只返回基本接口(interface)。对于 Direct3D 11,这是一个 ID3D11Device
。
If you want to get an interface to say 11.1, you then use
QueryInterface
on theID3D11Device
asking for aID3D11Device1
. It would fail on a DirectX 11.0 system, but works on a DirectX 11.1 or later system.
对于使用 Direct3D 的 C++ 程序员,该设计有意将“COM”保持在最低限度(俗称“COM lite”)。真正使用足够的 COM 可以更轻松地处理随时间变化的接口(interface)并提供合理的 ABI。 Direct3D 工厂函数是来自已知 DLL 的简单 C 调用导出,因此您甚至不必处理标准 COM 工厂,事实上,如果您尝试使用 CoCreateInstance,API 将无法正常工作
。您可以通过标准 MIDL compiler 的一些宏在技术上使用 C与 C++ 定义一起生成,但这样做有点挑战,而且最近没有经过特别好的测试。
作为 Direct3D COM 的使用者,您真正需要了解的是 IUnknown
引用计数和查询的基础知识——今天最好使用 Microsoft::WRL::ComPtr 来完成。智能指针——以及如何正确检查 HRESULT
值——参见 ThrowIfFailed .
See The Component Object Model and Reference Counting (Direct3D 10)
关于c++ - 什么是 Direct X 虚拟表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45207273/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!