Cetting lpVtbl of COM
BlitzMax Forums/BlitzMax Programming/Cetting lpVtbl of COM
| ||
For example, the Interace in pub.mod/directx.mod/d3d7.bmx called IDirect3DDevice7. How I can get the lpVtbl? lpVtbl is a Pointer(I think), of the table contains all adresses of the interface methods of IDirect3DDevice7 like Method SetRenderState(renderstate,value). So I can get acces like MyDevice.lpVtbl.SetRenderState(MyDevice, D3DRENDERSTATE_LIGHTING, True) Or it must be like: Global Function SetRenderState:Int(MyDevice:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) SetRenderState = MyDevice.lpTbl[XYZ] SetRenderState(MyDevice, D3DRENDERSTATE_LIGHTING, True) But there are only methods defined in the IDirect3DDevice7 Interface not a member lpVtbl . I hope you understand me :) need this, to overload some DirectX methods by changing the entry in the table to my own method/function. cu olli Edit: Oh, "Getting" as "Cetting" *rolleyes* |
| ||
I understand what your asking but never thought of really trying what your attempting but dont think it will work. That considered the VTable pointer is the interface. So if you consider the IDirect3DDevice7 interface that is the VTable. So get instance of IDirect3Device7 and cast that to Int Ptr. Here is what I am think although untested, that BMax can pull it off. ie. local d3d:IDirect3DDevice7= driver.GetDevice.. or something local vtable:Int Ptr = Int Ptr(d3d) You then have the Vtable as array of Int's. The offset to the function would be count the number of entries. Then cast that as a function pointer that matches the signature of the VTable exactly which means you have to handle THIS as impled first paramater. vtable[22]=MySetRenderState(d3d:IDirect3DDevice7,RenderStateType:Int, RenderState:Int) I just really dont think this will work, as I think the VTable is stored in a code segment and might not modifiable, I could be wrong as I never thought to try this. Good luck. Doug Stastny |
| ||
Ohh, the instance is the vtable. Hehe, yes thats very simple :) Thank you! I will post, if it work... cu olli |
| ||
I made a slight mistake, the instances first pointer is to the VTables. So say we have a Instance D3DDevice local Vtable:Int Ptr = Int Ptr(Int Ptr(D3DDevice)[0]). The first address of instance points to the Vtable. Sorry was late when I wrote that forgot the double dereference. Doug Stastny |
| ||
Yeha, this works fine! renderstate.bmx: SuperStrict Framework PUB.DirectX ' Don't remove this main function! Function DllMain:Int(hinstDLL:Byte Ptr,fdwReason:Int,lpvReserved:Byte Ptr)"win32" Select fdwReason Case 1 ' DLL_PROCESS_ATTACH Case 2 ' DLL_THREAD_ATTACH Case 3 ' DLL_THREAD_DETACH Case 0 ' DLL_PROCESS_DETACH End Select Return True End Function ' Don't remove the EXPORT comment! Function ChangeShading:Int(Device:IDirect3DDevice7, Mode:Int) "win32" 'EXPORT Local VirtualTable:Int Ptr Local SetRenderState:Int(This:IDirect3DDevice7, RenderStateType:Int, .. RenderState:Int) "win32" VirtualTable = Int Ptr(Int Ptr(Byte Ptr(Device))[0]) SetRenderState = Byte Ptr(VirtualTable[20]) Return SetRenderState(Device, D3DRS_SHADEMODE, Mode) End Function Function ChangeShading2:Int(Device:IDirect3DDevice7, Mode:Int) "win32" 'EXPORT Device.SetRenderState(D3DRS_SHADEMODE, Mode) End Function MakeDLL renderstate.bmx D:\BlitzMax renderstate.decls: .lib "renderstate.dll" ChangeShading%(D3DDevice%, Mode%) : "ChangeShading" Const D3DSHADE_FLAT = 1 Const D3DSHADE_GOURAUD = 2 Const D3DSHADE_PHONG = 3 Graphics3D 800,600,32,2 Global Device = Int(SystemProperty("Direct3DDevice7")) Camera = CreateCamera() PositionEntity Camera, 0, 0, -4.0 Light = CreateLight() RotateEntity Light, 60, 30, 0 Sphere = CreateSphere() While Not KeyHit(1) If KeyHit(2) ChangeShading Device, D3DSHADE_FLAT If KeyHit(3) ChangeShading Device, D3DSHADE_GOURAUD If KeyHit(4) ChangeShading Device, D3DSHADE_PHONG RenderWorld() Text 0, 0, "Press 1,2 or 3 to change the Render Style" Flip() Wend End Now I will test, if I can overload this method. And one question: How can I find out, what index has a method in the vtable? cu olli Edit: Get I right, when I say, that I must 3 + Method Place? 3 stands for the methods of IUnknown(QueryInterface, AddRef and Release). In IDirect3DDevice7 is SetRenderState the 18th Method has also an Index of 17. So the entry is 3 + 17 -> 20 and works fine. The same for IDirectDraw7 with CreateSurface. |
| ||
Very cool! I see you got to the vtable. The code you wrote BTW is how you deal with COM Objects in straight C code. Well to see if it works try to stuff function pointer back into the VTABLE. I still thank that may cause a WEP error on systems that support WEP. Oh what was MAKEDLL? I saw there is some code for making DLLs added to BMAX but havent seen MAKESDLL. Looks like it parses the Export comment? I have played with making DLLs by manually linking but a tool that sets up the link instead of my batch file would be nice. Doug Stastny |
| ||
MakeDLL: http://www.svenberra.net/MakeDLL.zip Very nice and simple tool :) Here is a test to overload SetRenderState. DX7Overloader.bmx SuperStrict Framework PUB.DirectX Const MB_OK : Int = $0 Const MB_ICONEXCLAMATION : Int = $30 Extern "win32" Function MessageBoxA:Int(hWnd:Int, lpText$z, lpCaption$z, uType:Int) End Extern Const VTBL_SETRENDERSTATE : Int = 20 Global VirtualTable : Int Ptr Global OrgSetRenderState : Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) Function DllMain:Int(hinstDLL:Byte Ptr, fdwReason:Int, lpvReserved:Byte Ptr) "win32" Select fdwReason Case 1 ' DLL_PROCESS_ATTACH Case 2 ' DLL_THREAD_ATTACH Case 3 ' DLL_THREAD_DETACH Case 0 ' DLL_PROCESS_DETACH End Select Return True End Function Function StartRecording(Device:IDirect3DDevice7) "win32" 'EXPORT ' Get virtual table from interface/instance VirtualTable = Int Ptr(Int Ptr(Byte Ptr(Device))[0]) ' Get original method OrgSetRenderState = Byte Ptr(VirtualTable[VTBL_SETRENDERSTATE]) ' Overload with own method VirtualTable[VTBL_SETRENDERSTATE] = Int(Byte Ptr(SetRenderState)) End Function Function StopRecording:Int() "win32" 'EXPORT ' Rewrite original method VirtualTable[VTBL_SETRENDERSTATE] = Int(Byte Ptr(OrgSetRenderState)) End Function Function SetRenderState:Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) ' Display some information MessageBoxA(0, "RSType: "+RenderStateType+"; RS: "+RenderState, .. "Overloaded method", MB_OK | MB_ICONEXCLAMATION) ' Use original method Return OrgSetRenderState(This, RenderStateType, RenderState) End Function make.bat MakeDLL DX7Overloader.bmx D:\BlitzMax Pause DX7Overloader.decls .lib "DX7Overload.dll" StartRecording(Device%) StopRecording() Test.bb Graphics3D 640, 480, 0, 2 Global Device = Int(SystemProperty("Direct3DDevice7")) Camera = CreateCamera() PositionEntity(Camera, 0.0, 0.0, -4.0) Light = CreateLight(2, Camera) Cube = CreateCube() RotateEntity Cube, 0.0, 45.0, 0.0 StartRecording(Device) RenderWorld() StopRecording() Flip() WaitKey() End It shows at first a message box with "RSType: 7; RS: 0" and than comes a memory access violation. cu olli Edit: If I forget: This is the idea of Tom(alias Tomspeed?) Edit2: Global OrgSetRenderState : Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) "win32" display 2 messageboxes and than comes the memory access violation |
| ||
This Global OrgSetRenderState : Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) needs to be Global OrgSetRenderState : Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) "win32" Doug Stastny |
| ||
I thought such use of unholy magic was forbidden by the council long time ago :) |
| ||
Oh fuck, I forget "win32" 2x here this working example:SuperStrict Framework PUB.DirectX Const MB_OK : Int = $0 Const MB_ICONEXCLAMATION : Int = $30 Extern "win32" Function MessageBoxA:Int(hWnd:Int, lpText$z, lpCaption$z, uType:Int) End Extern Const VTBL_SETRENDERSTATE : Int = 20 Global VirtualTable : Int Ptr Global OrgSetRenderState : Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) "win32" Function DllMain:Int(hinstDLL:Byte Ptr, fdwReason:Int, lpvReserved:Byte Ptr) "win32" Select fdwReason Case 1 ' DLL_PROCESS_ATTACH Case 2 ' DLL_THREAD_ATTACH Case 3 ' DLL_THREAD_DETACH Case 0 ' DLL_PROCESS_DETACH End Select Return True End Function Function StartRecording(Device:IDirect3DDevice7) "win32" 'EXPORT ' Get virtual table from interface/instance VirtualTable = Int Ptr(Int Ptr(Byte Ptr(Device))[0]) ' Get original method OrgSetRenderState = Byte Ptr(VirtualTable[VTBL_SETRENDERSTATE]) ' Overload with own method VirtualTable[VTBL_SETRENDERSTATE] = Int(Byte Ptr(SetRenderState)) End Function Function StopRecording:Int() "win32" 'EXPORT ' Rewrite original method VirtualTable[VTBL_SETRENDERSTATE] = Int(Byte Ptr(OrgSetRenderState)) End Function Function SetRenderState:Int(This:IDirect3DDevice7, RenderStateType:Int, RenderState:Int) ' Display some information MessageBoxA(0, "RSType: "+RenderStateType+"; RS: "+RenderState, .. "Overloaded method", MB_OK | MB_ICONEXCLAMATION) ' Use original method Return OrgSetRenderState(This, RenderStateType, RenderState) End Function Thaaaaaank youuuuuuu! :) cu olli |
| ||
All that crazy voodoo. Everyday I am more impressed with what can be pulled off in BlitzMax. Here is sample for those who want to interface C++ objects. It usings simple reference counted interfacing techniques. This also plays with VTable like Vertexes. Still not sure if this is Vtable messing with is safe with all processors but the interfaced objects are fine. Need to try it out on a AMD Processor i think the have support for WEP. C++ Code #include <stdio.h> // Sample interfaced class cppobject.cpp // Delecare an Interface for class // note we using reference counting to implement cleanup class IObject { public: virtual int _AddRef()=0; virtual int _Release()=0; virtual int Add(int X,int Y)=0; // This is important to be pure interface }; // Class that implements the interface class TestObject: public IObject { private: int refCount; public: TestObject() { refCount=1; printf("Created TestObject\n"); fflush(stdout ); } ~TestObject() { printf("Destroyed TestObject\n"); fflush(stdout ); } virtual int _AddRef() { refCount++; return refCount; } virtual int _Release() { refCount--; if (refCount==0) delete this; return refCount; } virtual int Add(int X,int Y) { return (X+Y); } }; extern "C" { IObject* CreateTestObject() { return new TestObject(); } } BMax code to use the Interfaced Object Superstrict Import "cppobject.cpp" Extern "C" Type IObject Method _AddRef:int() Method _Release:Int() Method Add:Int(X:Int,Y:Int) End Type Function CreateTestObject:IObject() End Extern Function MyAdd:Int(obj:IObject , X:Int,Y:Int) Print "Subclassed-Subtracting" return X-Y End Function local _saveAdd:Int(obj:IObject , X:Int,Y:Int) Print "Testing Interfaced C++ Object" local obj:IObject= CreateTestObject() print "1. Adding 1+2="+obj.Add(1,2) local vtable:Int Ptr= Int Ptr(Int Ptr(Byte Ptr(obj))[0]) _saveAdd=Byte Ptr(vtable[2]) vtable[2]=Int(Byte Ptr(MyAdd)) print "2. Adding 1+2="+Obj.Add(1,2) obj._Release() obj:IObject= CreateTestObject() print "3. Adding 1+2="+Obj.Add(1,2) vtable[2]=Int(Byte Ptr(_saveAdd)) print "4. Adding 1+2="+Obj.Add(1,2) obj._Release() obj=null print "Done" All kinds of fun stuff. Can be done with this :) I have some code on my HD somewhere that implements an interface by creating a VTable in code and passing it back to C++. It allows C++ code to call BlitzMax Objects. Cant marshal BMAX objects to C++ but can marshal an interface constructed in BMAX. I need to look for it. Doug Stastny |
| ||
greetings all :) Budman! hope all is well its been a while :) my interest is definately piqued by this vtable stuff for potential use in the Irrlicht mod. if im understanding this correctly, you can essentially override a method by changing the vtable pointer to point to a BMAX function. is this a correct statement? when trying the above code im getting an unhandled memory exception on the line: vtable[2]=Int(Byte Ptr(MyAdd)) any thoughts on what i might be doing wrong? P4 with XP Pro. is the vtable cross platform? the only problem i see with the above is getting access to the object itself from within the remapped function. have you found a way to do this Budman? thank you :) |
| ||
Hey GMAN! Not sure why you are getting the Access Violation other than maybe your CPU supports DEP. Mis spoke and said WEP above(Duh! thinking wireless). I retried my posted code and it still works on my machine P4 xppro(What version of P4 do you have?). What version of BMax you using? Maybe somethings changed in regards to casting resoultion in BMAX, dont think the C++ compiler will mater. Now I dont think hooking into the VTable at runtime is a good idea. I was just was helping with technically how it could be done. Not that I think its good idea :) The part more usefull is the technique for interfaces. It should be cross platform. As its standard C++ implementaion of interfaces, however platform compilers may deal with it differently implementaion wise by platform. I have tested technique on MS Visual Studio DLL and GCC DLL, direct CPP in BMAX like above on windows and works fine. Havent booted the Linux box in a while. As for VTables and getting Bmax Objects into C++. I think I know what your wanting to do with that in regards to Irrlicht. Infact I was looking at Irrlicht source the other day and noticed most of the interfaces for the objects are PURE so theorically your wrapper can be much easier. As I think you can remove alot of the wrapping layers to improve performance. I do have code that implements a C++ interface in BMAX then passes the BlitzMax Objects interface back to the C++ code so the C++ calls the BMAX objects methods. So the area of Irrlicht that you want to derive scene nodes in BMAX should be quite doable. Mark and Skid might not like it, but it works and is hugely faster than handles and TMAP. And can be encapsulated enough to maintain if they decide to change the object implementation as it messes with the internals of the Garbage collection. I havent shared it since its one thing to maintain my code another to give novices a tool to shoot themselves in head and complain to Mark and Skid, that 3rd party code broke when the updated the compiler. If your around this weekend I can try and get togther example for you. As I am still lost trying to determine what 3d engine to use. If we can get the technique to work in Irrlicht I might swing back to that. Doug Stastny |
| ||
hey Budman :) sorry for the delay. im deep into upgrading the Irrlicht mods and a few other minor things. Not sure why you are getting the Access Violation other than maybe your CPU supports DEP. that was it. went in through system properties and allowed the application. that fixed it. the fix in itself though makes this concept unviable IMO. noticed most of the interfaces for the objects are PURE so theorically your wrapper can be much easier. you are correct. i have not done this because i lose flexibility. you can only derive other externed types from externed types and you cant override any methods at all. there are cases where i change the parameters some to make it easier for BMAX. given that, im sure there are still some i could do that way. If your around this weekend I can try and get togther example for you. my apologies for not getting back quicker. i think the concept is good and id be interested in seeing it in action... but as always im pretty leery about changing anything in the BMAX base mods because it causes everyone using it to have that change. |
| ||
GMAN, I figured as much with the DEP problem. Hopefully Vertex will read this thread so he sees what he was trying to do is not practicaly for deployment. Since all new processors support DEP. My old 3ghz doesnt which is why I coulndt reproduce, Although I think there is some windows API commands that can work around this. As for my VTable stuff, My solution doesnt change anything in Base Mods. Estentailly it works by defining a C++ PURE Interface and creating a VTABLE by hand then passing that VTable back into the C++ code. I am curious about DEP though. The trickery is helper function to get to the object that maps to the vtable. Would be easy if MAX had Object Ptr but Mark is pretty insitent that us meager programmers cant handle that, so we are faced with implementing our own. I think Irrlicht if I remmber uses ISceneNode and you created a wrapper in C++ that refelcts back to a BlitzMax Object that can then be overriden. This is estentailly the same thing where except you implement the interface with Blitz Max and create the VTABLE which you pass back to C++. You can then override the object in BMAX that creates the VTable. My big concern and problem that I have been having with all the wrappers is speed hits due to context switching of the wrapping layers. What I mean by this is the overhead of all the procedure calls. Every time you call a method/function the processor has to save the context of the registers and stack so that when the procedure returns it gets restored. This is very expensive in CPU utilization. For example look at the Vector Library in Irrlicht. Just adding two vectors togther with BlitzMax is slow and even slower with the wrapper in place. Only way to implement effective vector operations in Blitz Max Currently is to code the operations out in inline. ie. X,Y,Z,X1,Y1,Z1,X2,Y2,Z2. X=X1+X1,... etc. This is PIA, and mistake driven not to mention hard to read. I'll try to get togther example with Blitz Max implmenting a C++ Interface, and maybe you can test it out with DEP and see if it will help or not. Doug Stastny |
| ||
I'll try to get togther example with Blitz Max implmenting a C++ Interface, and maybe you can test it out with DEP and see if it will help or not. would be very much appreciated thank you. |
| ||
GMAN Ok here is the sample I promised. Let me know if it works with DEP. If not I will recode the VTable implmentation. Since I am unsure if it has to be marked executable or not. C++ Code. #include <stdio.h> extern "C" { /* Simple Functions to get Object from Pointer and Back */ void* ObjectFrompVtbl(void* Vtbl) { return (void*)(*(((int*)Vtbl)+1));} } // Sample interfaced class cppobject.cpp // Delecare an Interface for class // note we using reference counting to implement cleanup class IObject { public: virtual int _AddRef()=0; virtual int _Release()=0; virtual int Add(int X,int Y)=0; // This is important to be pure interface }; // Some Test functions to pass our BMAX interfaced object too static IObject* instance=0; extern "C" { void SetInstance(IObject* io) { if (instance) instance->_Release(); instance=0; if (io) { instance=io; instance->_AddRef(); } } int AddInstance(int X,int Y) { if (instance) { return instance->Add(X,Y); } else return 0; } } BMax Code Superstrict Import "cppobject.cpp" Rem Help Function to Tranlate VPtr to Object Handle This can be changed around to play with TMAP Handles but that is too slow This works and is based upon the structure of the Object in BMAX, has been this way since version 1. Use to be able to do with Object Ptr but removed end Rem Extern "C" Function ObjectFrompVtbl:Object(pVtbl: Byte Ptr) End Extern Rem This is Blitz Max interface definition corrosponding to C++ Interface Definition End Rem Extern "C" Type IObject Method _AddRef:int() Method _Release:Int() Method Add:Int(X:Int,Y:Int) End Type End Extern Rem This is our definitoon of the VTable Since I cant test this on machine with DEP, might need to implment differently not a big deal to change to work with DEP just need to make OS Specific calls to allocate executeable chunk of memory End Rem Type TIObjectVTable Field _AddRef:Int(pVtbl:Byte Ptr)=vAddRef Field _Release:Int(pVtbl:Byte Ptr)=vRelease Field Add:Int(pVtbl:Byte Ptr,x:Int,Y:Int)=vAdd End Type Rem These functions implment the VTable and fixup the calls to the Objects, ideally this would be inline ASM to use a JMP instead of CALL but here we are SOL so we need to deal with overhead of CALL End Rem Function vAddRef:int(pVtbl:Byte Ptr) Return TIObject(ObjectFrompVtbl(pVtbl))._AddRef() End Function Function vRelease:Int(pVtbl:Byte Ptr) Return TIObject(ObjectFrompVtbl(pVtbl))._Release() End Function Function vAdd:Int(pVtbl:Byte Ptr,X:Int,Y:Int) Return TIObject(ObjectFrompVtbl(pVtbl)).Add(x,y) End Function Rem Only need one instance of VTABLE for all instances of Object End Rem Global IObjectVTableVtblInstance:TIObjectVTable=New TIObjectVTable Rem Here is our base definition of the object that implments the VTABLE End Rem Type TIObject Field _Vtable: Byte Ptr ' these two variables must be in sequence Field _Handle: TIObject ' this allows us to implment multiple interfaces the fixup code gets the instance handle Field _RefCount: Int ' since we are interfaced _Ref counting is good idea to track our external allocations Method New() Print "Created" _Vtable= Byte Ptr(IObjectVTableVtblInstance) End Method Method Delete() Print "Deleted" End Method Method IObject:IObject() Final ' this code looks tricky but not too bad IObject is not Blitz Object its a pointer ' we are stuffing the VTable value into it and returning it Local u:IObject Local b:Byte Ptr=Varptr(u) Int Ptr(b)[0]=Int(Varptr(_Vtable)) ' Add Ref since we gave out our VTable Ref we should add one to it ' careful use here required since as soon as we give out object it sets count to 1 _AddRef() Return u End Method Method _AddRef:Int() Final ' if we are giving out externa ref set our handle ' this prevents GC as well as allows interface to be cracked If _RefCount=0 Then _Handle=Self _RefCount:+1 Print "RefCount"+_RefCount Return _RefCount End Method Method _Release:Int() Final _RefCount:-1 ' No more external references then we set handle to null for clean up If _RefCount=0 Then _Handle=Null Print "RefCount"+_RefCount Return _RefCount End Method Method Add:Int(x:Int,Y:Int) Return X+Y End Method End Type Type TIObjectSubtract extends TIObject Method Add:Int(X:Int,Y:Int) return X-Y End Method End Type ' Test it Extern "C" Function SetInstance(io:IObject) Function AddInstance:Int(X:Int,Y:Int) end Extern Print "Test One" Print "We play with interface locally in BMAX" Print "Note: we dont have variable of TIObject but the interface" global obj : IObject= (new TIObject).IObject() Print "1+2="+obj.Add(1,2) Print "Try to collect it" GCCollect() Print "Nope!" Print "Release our Interface" obj._Release() Print "Released it so now should collect" GCCollect() Print "Success" Print "" Print "Test Two" Print "Externally with C" obj =(new TIObject).IObject() Print "Setting to external C Variable" SetInstance(obj) Print "3+4="+AddInstance(3,4) Print "Release External Ref" SetInstance(null) Print "Release our local ref" obj._Release() GCCollect() Print "Success" Print "Test Three" Print "Extending BMAX Object" obj= (new TIObjectSubtract).IObject() SetInstance(obj) Print "Release our local we dont need anymore" obj._Release() GCCollect() Print "Still alive since external reference valid" Print "5+4="+AddInstance(3,4) Print "Release our external Ref" SetInstance(null) GCCollect() Print "Success" Now the function that translates the VTable to Object can be changed to use handles but that layer of using TMAP with ObjecttoHandle HandletoObject plan and simple sucks. Mark really cant change this to fail and as long as used with the pattern here it cant fail or leak. Let me know about the DEP issue though as that has me really curious as I have an OGRE wrapper that I have been working off and on using this interface technique to override OGRE Classes, and if the DEP causes a problem I will have to recode the allocation of the VTables. Doug Stastny |
| ||
thank you very much for the detailed example. it did run fine on the machine that had the issue and interestingly enough, i didnt have to select the EXE to allow it as i did the other one. i would like to toggle the option again and try it one more time on that machine. will have to wait a couple days though until im at that machine again. i have not done a deep analysis of the code yet, but i do have a question. what if there are methods on the underlying object you dont want to override but still be able to run the default code? ISceneNode from Irrlicht for example, has base methods on the interface that i would want to keep. |
| ||
erm..perhaps im mistaken - but i thought making dll's with bmax was forbidden? - hmmm...if that is infact what your doing, you might want to check up with BRL to make sure.. ..anyhoO..back to playing about in fasm ;) |
| ||
Gman, cool thanks for the test. I figured it wouldnt have the same problem as the allocated memory should be ok. I think the issue as I understand with DEP is that the datasegments produced by the compilers VTABLE are marked readonly hence the DEP when messing with the VTable. As for dealing with Irrlicht, I was looking at it again today and the objects although he calls them interfaces there not PURE. He has destructors and such. What I was thinking for Irrlicht would be to use the interface as a callback mechinism to a base object you create like you do now, but instead of all the function mapping you use the interface as delagte style implementation. Defoc8, I am not making the DLL with BMAX, I am passing interfaces to my BMAX objects back to my DLLs and C++ Objects in obj file. It allows me to for implement delgate patterns to my own engine code based upon OGRE. This allows for a true OOP interaction with OGRE not a function based wrapper. I think BRL is going to change the DLL license thing as they have been inconsistent. The license changed after release, my orignal license had no stipulation and think the issue is not with writting DLLs but wrapping thier code and selling a DLL. ie. wrapping Max2d and selling it as your own code. If you look at the change log in Appstub.c youll see there is comments for adding support for DLLs. Prior to that change the Garbage collector was not being initialized so DLLs made with MAX that used objects would leak. but simple function DLLs would be fine. Oh and if you get a fast otimized matrix library written in ASM I might be interested :) Doug Stastny |