Почему Direct2D и DirectWrite не используют традиционные COM-объекты? - PullRequest
4 голосов
/ 15 мая 2010

Я играю с небольшим 2D игровым движком на C # и решил использовать Direct2D и DirectWrite для рендеринга. Я знаю, что есть Windows API Code Pack и SlimDX, но мне бы очень хотелось покопаться и написать интерфейс с нуля. Я пытаюсь сделать это без Managed C ++, но Direct2D и DirectWrite не используют традиционные объекты COM. Они определяют интерфейсы, которые являются производными от IUnknown, но, по-видимому, нет никакого способа использовать их из C # с COM-взаимодействием. В d2d1.h есть IID, но нет CLSID.

Конечно, я действительно новичок в COM взаимодействии, так что, возможно, я просто что-то упустил. Может кто-нибудь пролить свет на эту ситуацию?

Ответы [ 3 ]

8 голосов
/ 15 мая 2010

Понял. Вы не можете создавать объекты напрямую, но d2d1.dll содержит экспорт с именем D2D1CreateFactory, который возвращает интерфейс ID2DFactory. Используя это, вы можете реализовать оболочку Direct2D без Managed C ++.

public static class Direct2D1Util {
    public const string IID_ID2D1Factory =
        "06152247-6f50-465a-9245-118bfd3b6007";

    [DllImport("d2d1.dll", PreserveSig = false)]
    [return: MarshalAs(UnmanagedType.Interface)]
    private static extern object D2D1CreateFactory(D2D1_FACTORY_TYPE factoryType,
        [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
        D2D1_FACTORY_OPTIONS pFactoryOptions);

    public static ID2D1Factory CreateFactory() {
        D2D1_FACTORY_OPTIONS opts = new D2D1_FACTORY_OPTIONS();
        object factory = D2D1CreateFactory(
            D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED,
            new Guid(IID_ID2D1Factory), opts);
        return (ID2D1Factory)factory;
    }
}

Я не буду включать все типы, потому что все они определены в d2d1.h, но вот как использовать код для получения фабрики:

ID2DFactory factory = Direct2D1Util.CreateFactory();

Убедитесь, что ваш ID2DFactory интерфейс имеет соответствующие атрибуты Guid и InterfaceType(ComInterfaceType.InterfaceIsIUnknown).

6 голосов
/ 15 мая 2010

«Windows® API Code Pack для Microsoft® .NET Framework» имеет управляемые библиотеки, которые обеспечивают доступ к Direct2D и DirectWrite.

http://code.msdn.microsoft.com/WindowsAPICodePack

Обновление

Хотя оболочки DirectX написаны на управляемом C ++, они создают управляемые библиотеки. Судя по всему, они могут быть использованы в C #. Есть много примеров, включенных в загрузку, которые делают именно это, то есть используют управляемые библиотеки оболочки C ++ Direct из C #.

Было бы очень полезно использовать функции Windows 7 в моем собственном приложении C #, поэтому я в настоящее время устанавливаю Windows7 SDK (так что я могу создать управляемое решение C ++ DirectX) и предоставлю возможность всего этого.

Я следую инструкциям по адресу:

http://blogs.msdn.com/msaleh/archive/2009/08/25/introducing-directx-features-of-windows-api-code-pack.aspx

Обновление 2

Следуя инструкциям в приведенной выше ссылке, я собрал управляемые библиотеки C ++, и вы действительно можете очень легко использовать их из C #.

Теперь я не уверен, правильно ли я понимаю, но вы просто рассматриваете какой-то способ использования Direct2D и DirectWrite из C # или это должен быть COM или P \ Invoke.

Я бы очень сомневался, что будет оболочка COM, так как это несовпадающая технология. COM не очень хорошо спроектирован для шаблонов высокочастотных вызовов методов, которые вы получаете в графическом программировании - он слишком медленный.

Если вы действительно хотите сделать P \ Invoke, вы всегда можете посмотреть заголовочные файлы DirectX (в Windows 7 SDK) и использовать инструмент для создания всех ваших заглушек вызовов P \ Invoke, например,

http://www.pinvoker.com/

Вероятно, это будет основной PITA, хотя и разрабатывать обертку таким образом.

2 голосов
/ 15 мая 2010

В codeplex есть проект, который предоставляет управляемые оболочки для Direct2D. Я понятия не имею, если это хорошо, но, скорее всего, исходный код поможет вам начать.

http://direct2dsharp.codeplex.com/

...