Seite 1 von 1

[C#] Unmanaged COM Objekte nutzen [Done]

Verfasst: 06.11.2012, 15:04
von RazorX
Servus,
ich will mir gerade ein kleines Tool schreiben und brauche dazu im C# die Möglichkeit den D3DCompiler anzusprechen. Der Funktionsaufruf von D3DCompile funktioniert auch und ein kleiner Testshader wird auch kompiliert (Rückgabewert ist S_OK und ich bekomme einen CodeBlob). Wenn ich dann aber versuche über GetBufferPointer() oder GetBufferSize() das Ergebnis abzufragen erhalte ich nur IntPtr.Zero bzw 0 zurück.

Code: Alles auswählen

// Definitionen
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("8BA5FB08-5195-40e2-AC58-0D989C3A0102")]
public interface ID3DBlob {
    IntPtr  GetBufferPointer();
    ulong   GetBufferSize();
};
          
[DllImport("d3dcompiler_43.dll", EntryPoint="D3DCompile", CallingConvention=CallingConvention.StdCall, PreserveSig=true)]
public static extern IntPtr Compile([In] IntPtr pSrcData, 
                                    [In] uint srcDataSize, 
                                    [MarshalAs(UnmanagedType.LPStr), In, Optional] String pSourceName, 
                                    [In, Optional]ShaderMacro[] pDefines, 
                                    [In, Optional] IntPtr pInclude,
                                    [MarshalAs(UnmanagedType.LPStr), In] String pEntryPoint, 
                                    [MarshalAs(UnmanagedType.LPStr), In] String pTarget, 
                                    [In] uint flags1, 
                                    [In] uint flags2, 
                                    [MarshalAs(UnmanagedType.Interface), Out] out ID3DBlob ppCode,
                                    [MarshalAs(UnmanagedType.Interface), Out, Optional] out ID3DBlob ppErrorMsgs);

// Aufruf
String      shader = "void vs_main(in float4 pos : POSITION, out float4 opos : SV_POSITION) { opos = pos; }";
ID3DBlob    pCode = null, pMsg = null, pDisassembly = null;
            
IntPtr  globalShader= Marshal.StringToHGlobalAnsi(shader);
IntPtr  hr          = D3D.Compiler.Compile(globalShader, (ulong)shader.Length, null, null, IntPtr.Zero, "vs_main", "vs_5_0", 0, 0, out pCode, out pMsg);
IntPtr  codePtr     = pCode.GetBufferPointer();
ulong   codeSize    = pCode.GetBufferSize();
Ich hoffe hier kennt sich jemand mit der Materie PInvoke und COM aus :) Danke im vorraus

Mit freundlichem Gruß
RazorX

Re: [C#] Unmanaged COM Objekte nutzen

Verfasst: 06.11.2012, 15:18
von dot
Verwend doch einfach z.B. SlimDX!?

Re: [C#] Unmanaged COM Objekte nutzen

Verfasst: 06.11.2012, 15:44
von RazorX
Sowohl SlimDX als auch SharpDX stürzen bei mir beim Kompilieren mit einer AccessViolation ab. Ich tippe einfach mal darauf das die noch nicht so 100pro Win8 kompatibel sind. Nichtdestotrotz weigert sich bei mir innerlich auch etwas für zwei DllImport Deklaration die ich benötige eine andere Bibliothek zu nutzen. Wie gesagt der Aufruf der D3DCompile Funktion funktioniert ja, nur eben das COM-Objekt liefert nichts brauchbares.

Re: [C#] Unmanaged COM Objekte nutzen

Verfasst: 06.11.2012, 17:13
von RazorX
Hartnäckigkeit zahlt sich aus:

Code: Alles auswählen

        [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("8BA5FB08-5195-40e2-AC58-0D989C3A0102")]
        public interface ID3DBlob {
            [PreserveSig]
            IntPtr  GetBufferPointer();
            [PreserveSig]
            ulong   GetBufferSize();
        };
Mit [PreserveSig] funktionieren die Methodenaufrufe und ich habe nun Zugriff auf D3DCompile und D3DDisassemble mit einem schlanken COM-Wrapper anstelle großer Third-Party-Lib.