разбираю ради интереса один пример на С++ с использованием интерфейса с последующей переброской его на рельсы - masm32 в примере используется интерфейс - IDirect3D8 функцией - Direct3DCreate8 инициализируется интерфейсом переменная - p_d3d p_d3d = Direct3DCreate8 (D3D_SDK_VERSION); дальше в коде можно пользоватся методами этого интерфейса например p_d3d->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &d3ddm); для этого нужно только чтобы этот интерфес был обьявлен в программе но например я не хочу заморачиватся с обьявлением этого интерфейса и зная смещение в интерфейсе метода - GetAdapterDisplayMode (32) я например просто хочу пользоваться этими непосредственными значениями как синтаксически это нужно записывать например в лоб p_d3d->32 (D3DADAPTER_DEFAULT, &d3ddm); не прокатывает да конечно если вызов метода сделать в Ассемблерной вставке __asm { lea eax,d3ddm push eax push 0 mov eax,p_d3d push eax mov eax,[eax] call [eax+32] } всё сработает как надо но вот как это сделать синтаксисом - С++ ведь ещё раз повторюсь я должен сначала отработать код на - С++ кто в теме подскажите пожалуйста
Заголовки с определением COM-интерфейсов на C++ как правило состоят из двух частей - дефолтные объявления в синтаксисе C++ и даунгрейд интерфейсов до C без классов. В данном случае: Код (C++): #if !defined(__cplusplus) || defined(CINTERFACE) ... #define IDirect3D9_GetAdapterDisplayMode(p,a,b) (p)->lpVtbl->GetAdapterDisplayMode(p,a,b) ... #else ... #define IDirect3D9_GetAdapterDisplayMode(p,a,b) (p)->GetAdapterDisplayMode(a,b) ... #endif Если приглядеться вокруг, то понятно, что Сишная версия трактует макрос DECLARE_INTERFACE таким образом, что вместо определения класса делает определение структуры с полем lpVtbl которое уже есть суть указатель на таблицу указателей на функции (структуру совпадающую получается с VTBL) которые первым дополнительным параметром принимают указатель на интерфейс. И таким образом COM можно использовать из Си без классов, а вышеобозначенные макросы позволяют писать единый код для Си и C++. Поэтому я бы пошёл по пути написания конвертера из синтаксиса этих довольно стандартных по структуре заголовочных файлов в синтаксис масма с похожим подходом и парой собственных макросов для естественных invoke-ов.
assch, Код (C): ((HRESULT (WINAPI*)(LPVOID, UINT, D3DDISPLAYMODE*))((*(LPVOID**)p_d3d)[8]))((LPVOID)p_d3d, D3DADAPTER_DEFAULT, &d3ddm); Но лучше интерфейс объявить
Большое спасибо rmn, за подсказки синтаксически всё хорошо работает но читабельность оставляет желать лучшего лучше уж использовать Ассемблерные вставки там хоть для меня интуитивно всё понятно я понимаю что интерфейс лучше объявить это я так просто ради спортивного интереса типа можно ли вместо лексем методов прописывать их смещения в интерфейсе мне для примера на С++ нужен был - Microsoft DirectX SDK (June 2010) я его скачал но в Microsoft Visual Studio 2013 где я ради интереса отсматриваю сишные примеры не как не смог сделать так чтобы виделся файл - d3dx9.h то есть строчка #include <d3dx9.h> не работает пришлось написать через кавычки полный путь #include "C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\d3dx9.h" только тогда заработало если в теме не подскажешь что нужно сделать чтобы в проекте виделся файл записанный между угловыми скобками
Надо просто добавить C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include в include path в настройках компилера и тогда будет работать просто #include <d3dx9.h> В проекте подключаемые файлы не появятся, но открыть их можно через контекстное меню (пкм по имени файла в директиве #include).
Не знаю как в масме, а в фасм имеется макрос "comcall", который делает удобным вызов com-методов. Просто передаём в аргументах интерфейс + метод, и на выходе получаем результат. В скрепке лежит инклуд для фасма "d3d9.inc" с описанием всех интерфейсов (структур для методов пока только три, остальные можно добавить из сишного хидера d3d9types.h). Вот пример: Код (ASM): format pe console include 'win32ax.inc' include 'equates\d3d9.inc' entry start ;//---------- .data hD3d9 dd 0 dspm D3DDISPLAYMODE aid D3DADAPTER_IDENTIFIER ;//---------- .code start: invoke CoInitialize,0 invoke Direct3DCreate9,D3D_SDK_VERSION mov [hD3d9],eax comcall [hD3d9],IDirect3D9,GetAdapterDisplayMode,NULL,dspm comcall [hD3d9],IDirect3D9,GetAdapterIdentifier,NULL,NULL,aid cinvoke printf,<10,' D3D9 example',\ 10,' ---------------------------',\ 10,' Driver......: %s',\ 10,' Name........: %s',\ 10,' Vid\Did.....: %04X:%04X',\ 10,' Resolution..: %d x %d',\ 10,' Refresh rate: %d MHz',0>,\ aid.Driver,\ aid.Description,[aid.VendorId],[aid.DeviceId],\ [dspm.Width],[dspm.Height],[dspm.RefreshRate] @exit: cinvoke _getch cinvoke exit,0 ;//---------- section '.idata' import data readable library msvcrt,'msvcrt.dll', ole32,'ole32.dll', d3d9,'d3d9.dll' include 'api\msvcrt.inc' include 'api\ole32.inc' include 'api\d3d9.inc'
Спасибо Marylin, за участие --- Сообщение объединено, 7 окт 2023 --- Marylin, хотел собрать твой пример на своём пакете - fasm которым я иногда пользуюсь когда попадётся какой нибудь пример на - fasm но у меня там нет файлов include 'api\msvcrt.inc' include 'api\ole32.inc' include 'api\d3d9.inc' если не трудно скинь мне эти файлы пожалуйста я дополню ими свой пакет - fasm я просто хочу понять вот например исходя из твоего примера comcall [hD3d9],IDirect3D9,GetAdapterDisplayMode,NULL,dspm откуда компилятор знает что у метода - GetAdapterDisplayMod только два параметра ведь при обьявлении интерфейса об этом не сказано
Вот эти файлы (положить в папку "fasm\include\api"), плюс в архив положил и софт, который создаёт такие инклуды импорта. Просто указываешь на нужную библиотеку из папки "windows\system32\..", и получаешь на выходе готовый инклуд. --- Сообщение объединено, 7 окт 2023 --- это нужно смотреть в сишном хидере "d3d9.h" - там указаны аргументы методов. компилятор об этом не знает.
Спасибо Marylin, за файлы особое спасибо за - CreateFasmAPI_Include.EXE теперь твой код и у меня заработал на моём пакете - fasm я не знаю всех тонкостей программирования на - fasm потому что работаю на - masm32 но был очень удивлён что если например к методу - GetAdapterDisplayMode приписать например лишние два параметра comcall [hD3d9],IDirect3D9,GetAdapterDisplayMode, NULL ,dspm, 1, 2 то компилятор примет это за чистую монету и на выходе из метода стек будет на 8 байт ниже так же ради интереса приписал лишний параметр к функции - Direct3DCreate9 invoke Direct3DCreate9,D3D_SDK_VERSION,0 на выходе стек опустился ещё на 4 байта Marylin, это общая политика - fasm где прописывания параметров у функций и методов целиком лежит на внимательности программиста или всё таки у - fasm есть механизмы отслеживания этих ошибок
используй в шапке инклуд "win32axp.inc", тогда fasm будет проверять кол-во параметров. но для этого нужно явно прописать число этих параметров в файлах, которые лежат в папке "fasm\include\pcount".