NG bug with fields that are functions?
BlitzMax Forums/Brucey's Modules/NG bug with fields that are functions?
| ||
I can't be sure of what I'm using, since I know of no official NG release. I decided to try the unofficial one posted yesterday on bmax-ng.com. I'm getting a compilation error on one of my modules related to this bit of code. Type TWindow Abstract Field _id:Int Field _name:String Field _window:TGadget Field _x:Int, _y:Int, _w:Int, _h:Int Field _hook:Object Field _eventMove:Object( data:Object ) Field _eventResize:Object( data:Object ) Field _eventGadgetAction:Object( data:Object ) Method New() _id = TWindowsMgr._windows.length TWindowsMgr._windows = TWindowsMgr._windows[ .._id + 1 ] TWindowsMgr._windows[ _id ] = Self End Method End Type The compiler says: 'struct BBClass_meld_winmgr_TWindow' has no member named 'm__eventResize_TObject' ... among other things. Am I right in guessing that the overloading is confused by my use of a field to store a function? ? for Brucey: The .7z you posted (a few weeks ago, I think) was compiling this and almost everything else I use just fine. Have recent releases gotten more strict? |
| ||
recent releases changed behaviour because they now use that overloading-feature you already mentioned. Internally it is mangling the function names: bla(i:int,f:float) becomes bla_i_f and so on My Assumption: Now you are calling a function-pointer which confused bcc-ng indead. It thinks "calling a function heh? let me mangle the name for your call..." and bamm, error. Maybe BCC-NG should lookup if there is a function-property in the class. No mangling needed there (overloading should not be available for it - should it?). Maybe it is a good idea to file an issue for Brucey. bye Ron |
| ||
Do you happen to have a line of code where you get the actual error? Thanks. |
| ||
The line reported is in the generated C file. It happens for all of the cases where I'm using a function pointer as a field: Field _eventResize:Object( data:Object ) , etc. |
| ||
Okay, but this compiles and runs for me:SuperStrict Framework brl.standardio Local window:TGuiWindow = New TGuiWindow window._eventMove = eventMove window._eventResize = eventResize window._eventGadgetAction = eventGadgetAction window._eventMove(window) Type TGuiWindow Extends TWindow End Type Type TWindow Abstract Field _id:Int Field _name:String Field _window:TGadget Field _x:Int, _y:Int, _w:Int, _h:Int Field _hook:Object Field _eventMove:Object( data:Object ) Field _eventResize:Object( data:Object ) Field _eventGadgetAction:Object( data:Object ) Method New() _id = TWindowsMgr._windows.length TWindowsMgr._windows = TWindowsMgr._windows[ .._id + 1 ] TWindowsMgr._windows[ _id ] = Self End Method End Type Type TWindowsMgr Global _windows:TWindow[] End Type Type TGadget End Type Function eventMove:Object( data:Object ) Print "eventMove" End Function Function eventResize:Object( data:Object ) Print "eventResize" End Function Function eventGadgetAction:Object( data:Object ) Print "eventGadgetAction" End Function |
| ||
Have recent releases gotten more strict? No, but there may be a generation issue under certain conditions when using function pointers. I need a reproducible example so that I can fix it :-) Thanks! |
| ||
Hmm, that's interesting. As I said, I'm using the latest build from bmx-ng.com. Perhaps that has an issue? Here's the entire module, then! The module grouping is meld.mod... This file is winmgr.bmx This file is __window.bmx |
| ||
Thanks. This should be enough: TWindowsMgr._windows[ 0 ]._eventGadgetAction( TWindowsMgr._windows[ 0 ] ) :o) |
| ||
FYI, if you use the -gdb option with bmk, it will conveniently generate line mappings in the C code to the original bmx lines. Then, if there's a problem with the generated C code, it should refer you back to the line in your BlitzMax source :-) |
| ||
Apologies for the delay... The latest bcc should generate the correct code now. |
| ||
it should refer you back to the line in your BlitzMax source Good to know!Thank you! No apologies necessary - that was fast! Is the executable available somewhere? I haven't gotten the hang of building it from source. I'm running 32-bit Win7 atm and my attempts so far have crashed. :( |
| ||
You should just be able to download the zip from github, and build bcc.bmx using your normal version of BlitzMax (console/release/full build). That will give you a bcc.exe that you can drop into your NG bin dir. |
| ||
Ah good, that worked. Thanks! However, now my gl module is just failing and doesn't give me a reason. It just says "failed to compile .." I was looking through the flags and tried -v, but it didn't help. Is there some other way to get more information about what is happening? EDIT: MaxIDE is giving me the old "module does not match command line module" message. Searching my memory banks, but can't see any reason this is happening. It has compiled before... EDIT 2: Oh right, haven't used MaxIDE for a while and forgot you can't just compile a module. So that error is bogus. However, I still have a problem and no information as to how to correct it. :/ |
| ||
MaxIDE allows for a custom command line. If you really want to see _where_ it hangs in BCC, you would need to compile BCC in debug mode from your MaxIDE. The custom command line then contains the params to compile your code file. Before writing wrong information I leave that open for Brucey. Think he will squash that issue faster than I explained (while not knowing it for sure) debugging BCC. Hints to narrow things down (and now, as you know how to compile BCC on your own ;-)): Download the revision before the fix for your issue: https://github.com/bmx-ng/bcc/commit/aaa3a7c82f9ff05ebab6868041ee5b2aab5fcb23 If that compiled BCC also fails already then the error was introduced before. If it just blames what your OP mentions, then the latest fix introduced the problem. Using that you could "traverse back in time" to find revisions not having a certain bug. Sometimes this has at least a little chance to help Brucey. And taking him off some workload helps spending him more time for other things. bye Ron |
| ||
Thanks, Derron. I'll definitely want to learn more about how to do that. MaxIDE is reporting errors if I use Build Modules, but that doesn't really allow me to tackle one module at a time like the command line does. I have learned that the overloading has introduced more strictness than I realized. It no longer does implicit conversions - understandable, but inconvenient. ;) |
| ||
Now that I think about it, it's odd that it doesn't fallback to implicit conversion, when there are no alternative functions to match up with. |
| ||
You can use -w option with bmk which will show warnings rather than error. The latest NG BRL and Pub modules should clean build without -w |
| ||
I'm afraid that didn't help. Still just getting a "failed to compile" message. I am getting messages from MaxIDE, though. It's just slow-going fixing them... |
| ||
What error messages are you getting, exactly? |
| ||
It's the overloading ... it is more strict about arguments matching exactly. If I passed a float into gl_viewport, it would still work because it would implicitly cast to an int. There are lots of things like that are breaking now. And they are slow to fix because, unlike in Blide, I can't zip around the source. But the point is that the command line isn't returning these errors or warnings. It's just telling me it failed. |
| ||
bmk 3.12 supports the -w option which raises these as warnings instead of errors, allowing you to still build things - with the option of tidying up your code at a later date. eg. ./bmk makemods -a -w brl.stream A typical example, taken from a TvTower build, looks like this: Compile Warning: In call to Method TRoomBoard.GetSignByOriginalXY:TRoomBoardSign(x:Int,y:Int). Argument #2 is "Float" but declaration is "Int". The build carries on. It will only stop when it finds an actual error. |
| ||
I know that's what's supposed to happen, but it is not. I have no idea why. |
| ||
I assume you have the latest versions?$ ./bmk -v bmk 3.12 mt-macos-osx-x64 / clang 700.1.81 (cpu x4) $ ./bcc -v bcc[ng] Release Version 0.76 On the command line, what error do you actually get? |
| ||
I'm using what was posted on bmx-ng.com, except that I recompiled bcc. Interestingly, bcc -v does nothing... bmk -v returns... bmk 3.11 win32-x86 / gcc 050100 (cpu x4) EDIT: Maybe it's not the debug version... heh. EDIT: Debug or no doesn't seem to matter. Still not getting anything when I type "bcc -v" on the command line.. |
| ||
You need bmk 3.12 Presumably the stuff dabs put together isn't the latest of everything? NG's bcc should always report the version number. The official one doesn't. If it doesn't give you a version number I doubt it will even compile anything... Btw, things will build faster if your bmk is built multi-threaded... |
| ||
Ok, except bcc is the only thing I've built. I grabbed the zip from github. I thought it was alright to build using any version of BMX. Is that not right? EDIT: ... EDIT 2: Disregard last edit. I forgot to put -t console in the command line when I compiled bcc. EDIT 3: Okay, I'm getting the compile errors in the console now. Guess 3.11 is sufficient for that, at least. |
| ||
3.12 adds the -w option... Which would allow your code to build, with warnings. |
| ||
That sounds great, but I just grabbed the zip off of github and recompiled and it's still coming up 3.11. Is it not yet committed? EDIT: Also had a question. Is the lib/ directory still searched for static libs? I was having another issue with my Bullet Physics library and wasn't sure if NG was finding it at all. Got any tips for static libs? |
| ||
BMK 3.11 ... is the latest BCC 0.76 ... is the latest Maybe it is a good option to add a hook to git to write the last commit hash to a file ... import this file and append it to the version string ("0.76 95e7568acf05fd"). Or each commit gets a pre-hook and adds to a counter. That way even little changes are tracked (the commits) and it is easier to narrow down which build is used. @ -w Like said in another thread it is even introduced in Brucey's MaxIDE variant. For now you need to use the console to fix the issues. The slower option is to not use "-w" and fix each upcoming error step by step (which might mean coming back to a previous file multiple times). Best is "-w" and then adjust code according to the warnings. @no failure output It should have output problems regardless of that issue (eg. "Multiple definition of xyz"). Maybe there is a little bug hidden in the code which is still existent now but not triggered because some code is executed before now. bye Ron |
| ||
Indeed, please disregard any mention of version 3.12. I shouldn't post when I should be asleep ;-) |
| ||
Okay, I'm getting the compile errors in the console now. You still haven't posted any errors yet, so I can't tell if there is an issue I need to fix or not. Got any tips for static libs? Put it in a module, and link to it that way. You can use the ModuleInfo option "LD_OPTS: -L%PWD%/relative/module/lib/path" and an Import "-lfile.a" (assuming that the library is named libfile.a) |
| ||
Just to note... I updated the package at bmx-ng.com just yesterday, and built all the base modules (well, what I regard as base modules brl, pub and maxgui) with "bmk makemods -a -w" and all was well it seemed, just tested versions:- Bmk 3.11 Bcc 0.76 Dabz |
| ||
You still haven't posted any errors yet I described them and then you posted an example - Argument #2 is "Float" but declaration is "Int" - so I thought it was unnecessary to repeat what you'd said. Sorry for not communicating that more effectively.Since my version was 3.11 and you said the warnings flag -w was introduced in 3.12, I thought I needed to wait for it to be committed. With 3.11, I'm still getting those warnings, but they are not just warnings - they are show stoppers. The part where I said I'm getting the compile errors in the console now just confirms that they are being reported (they weren't before because I forgot to use -t console). EDIT: Seems it's only "Unable to convert from Void to Int" errors now; at least that's all I'm encountering, atm. I remember when I converted to SuperStrict, I was surprised those weren't being caught. Guess now I actually have to fix them. :P EDIT 2: Still getting Argument #1 is "Long" but declaration is "Int" type errors that used to be implicit conversions. EDIT 3: Here's another line that is now an error... Byte[]( GetBMaxObject( Byte Ptr ci + off ) )[ ary1 ] = mb <<== Error: Unable to convert from ManaInternalExtendable to Int (ci is type ManaInternalExtendable) Byte[]( GetBMaxObject( Byte Ptr ( ci ) + off ) )[ ary1 ] = mb <<== Now ci needs parentheses to work... NOTE: I don't mind things being more explicit, but it seems these changes were unnecessary before the overloading stuff was added. I updated the package at bmx-ng.com just yesterday Yes, Dabz, that's what I have, too. 3.11 and 0.76 respectively. |
| ||
Put it in a module, and link to it that way. You can use the ModuleInfo option.. For now you need to use the console to fix the issues. As I said, a few weeks ago, I snagged the .7z version Brucey posted (for a test) and everything, other than my Bullet module, was working without any changes. I was most impressed and I hope I can get there again. ;)EDIT: I'm getting a "skipping incompatible <blahblah>.a when searching for -lblahblah" error with the Bullet module. I believe this is unwind_resume errors and it is my understanding that this is because of objects compiled with different versions of MinGW. However, I compiled the Bullet .a using CodeBlocks and the same version of MinGW. Not sure what else to check - maybe there is some flag I need? |
| ||
Incompatible usually means one is 64-bit and the other is 32-bit. Byte[]( GetBMaxObject( Byte Ptr ( ci ) + off ) )[ ary1 ] = mb Things like this.. probably an issue I can fix. |
| ||
Byte Ptr ci + off This one doesn't appear to be a recently created problem, as I have tested it on an older release and it brings up the same error. Presumably it should handle the plus at that point in a different way, so you end up with : (Byte Ptr ci) + off |
| ||
And btw, code like this:Byte[]( GetBMaxObject( Byte Ptr ( ci ) + off ) )[ ary1 ] = mb is probably rather dangerous with the new compiler, unless you really know what you are doing. Especially since "off" may need to be different when compiled between 32/64-bit. Of course, YMMV... I've patched the code so that only the left-hand-side of the binary expression is cast. Hopefully that doesn't break anything else :-p |
| ||
Which version was the one you posted as a result of "TomToad's 10 Step Guide to Misery?" In that version, everything compiled and worked with no changes and with only two exceptions - my Bullet module and the sound in Digesteroids. In any case, I don't mind adding the parentheses too much. But thanks! Incompatible usually means one is 64-bit and the other is 32-bit. Ah, that was it - this time (still have another issue with it, but I won't ask until I look it over more). The Bullet module (and to a lesser extent, TheoraPlayer) was the reason I decided to try NG. I've been messing around with so many different versions of MinGW and legacy BMX that I think I'm starting to get confused (even more than usual). :( Especially since "off" may need to be different when compiled between 32/64-bit. Indeed - one disaster at a time. :p |
| ||
New issue:Method GetFloatArray:Int( name:String, fa:Float[] Var ) Local dn:ManaDataNode = GetNode( name ) If Not dn Then Return False Local v:Float[] = Float[]( dn.GetObject() ) If Not v Then Return False fa = v <<<< THIS LINE IS REPORTED BY -gdb Return True EndMethodThis function is part of a generic node serialization module. I'm getting the following error: incompatible types when assigning to type 'BBArray {aka struct BBArray}' from type 'BBARRAY {aka struct BBArray *}' |
| ||
Which version was the one you posted as a result of "TomToad's 10 Step Guide to Misery?" That was normal BlitzMax with my BMK. It wasn't the NG bcc/compiler. That's probably why mostly worked :-p So, it seems you haven't actually tried NG until now - hence the issues you are getting. I don't mind adding the parentheses too much The latest bcc on github has a fix for the casting - or at least it fixed the example you provided. If you find other related issues, please tell me about them. |
| ||
Thanks, it fixed the casting. I've reported a new one. ^^ It wasn't the NG bcc/compiler Oooohhh, I thought that's what TomToad's post was about. Now I feel silly. |
| ||
New issue... Interestingly, it generates and compiles okay on OS X... The generated code looks correct : parameter : ... ,BBSTRING bbt_name,BBARRAY* bbt_fa){ your error line : *bbt_fa=bbt_v; both of which looks good. |
| ||
Tested on Win7, Mingw TDM 5.1, and it compiles okay too. This is what I am testing :SuperStrict Framework brl.standardio Type ManaDataNode Method GetObject:Float[]() End Method Method GetFloatArray:Int( name:String, fa:Float[] Var ) Local dn:ManaDataNode = GetNode( name ) If Not dn Then Return False Local v:Float[] = Float[]( dn.GetObject() ) If Not v Then Return False fa = v ' <<<< THIS LINE IS REPORTED BY -gdb Return True End Method End Type Function GetNode:ManaDataNode(name:String) End Function |
| ||
Should be ...Method GetObject:Object() ...perhaps the cast is not functioning? |
| ||
I changed that, but it still compiles okay here. Does this example compile for you, or not? |
| ||
Does this example compile for you, or not? It does. Have no idea what is happening. |
| ||
Do you happen to have your code split into multiple files ? Or does ManaDataNode extend from something defined in another file? bye Ron |
| ||
Yes, it extends something. I'll try to come up with a small test that breaks. |
| ||
Here's the smallest test I could come up with - it involves two modules. ManaNode.mod Test.mod ManaNode.mod compiles ...Test.mod brings up the error. |
| ||
Does not need to be a module, should fail with normal imports too. bye Ron |
| ||
Thanks for taking the time to get a working example :-) The latest bcc on github fixes the problem. You'll need to rebuild everything. |
| ||
Hmm, the test works, but my full module still produces the same error. :( Guess I'll have to come up with another test case. |
| ||
Also wondering why you do use something seemingly "game XY specific" as a module compared to normal imports. Did you recompile all the modules (just to avoid potential other bugs) as Brucey wrote? bye Ron |
| ||
Well, there's nothing "game XY specific" above, so I'm not sure what you're asking. Yes, I rebuilt all modules, but it's possible I missed something. Like I said, I'll try to come up with another test case. |
| ||
Maybe I misinterpreted "Mana" in your modulename ... soundes RPGish :-) If possible, you could mail Brucey the module (if you are not able to cut it down to something "small"). If I had "not that easily reproduceable" bugs, they often were connected to imports. So when trying to replicate it in a small sample, you might need to create multiple imports/modules (similar to your real world setup). bye Ron |
| ||
Ah, I see. Mana is the name of my game engine...nothing to do with the RPG. I will put a test together, but it's a bit less of a priority at the moment because everything is working again with vanilla BMX. |
| ||
Oh, one thing I noticed: If you remove the GetObject and GetNode methods from the ManaBinaryNode type, it compiles even though it should complain. GetObject and GetNode are declared Abstract...unless there's been some change in NG, as far as that goes. Perhaps it only checks that if the method is called somewhere? |
| ||
If you remove the GetObject and GetNode methods from the ManaBinaryNode type, it compiles even though it should complain. Why should it complain? You are simply declaring a type. Legacy BlitzMax doesn't complain either. However, if you try to create an instance of it (with New), you will see an appropriate error. |
| ||
if you try to create an instance of it Ah, that's right. Should've realized... |
| ||
my full module still produces the same error Perhaps it is several imports deep... If you want you can look at the .i file in the module, find the relevant method and see if it parameter is declared with "Var" or not. If it isn't then I guess there's still something to fix somewhere... |
| ||
see if it parameter is declared with "Var" or not Thanks a lot for your help. I'll let you know if anything else comes up. ... EDIT: Modules are all compiled, but when I tried to compile my test app, a number of TheoraPlayer undefined references came up... ...glue.cpp:151: undefined reference to 'bah_theoraplayer_common_TTheoraGenericException__create' ...etc. Any idea why? |
| ||
bah.theoraplayer has now been updated to support overloading. |
| ||
Thanks, now it compiles! Unfortunately, nothing happens when I run it. Probably something I've missed. :( |
| ||
If you need a hand with debugging, my email address is on my user profile. |
| ||
Thanks, that's nice of you. I'll try to work it out on my own, first. :) One question ... how compatible are NG and vanilla? Which changes that I make for NG's sake will make it incompatible with vanilla? |
| ||
At a high-level they are mostly compatible. Things like the casting for the recent NG overload work is fine for the old compiler too. Other stuff that doesn't appear to work with the old compiler that you need to change for NG, you can wrap the code in ?bmxng ' new ?not bmxng ' old ? And the code will then work with either. NG prefers to work with Ptr rather than Int for all external pointers - since a pointer is NOT 4 bytes in 64-bit land. That's the biggest change concerning compatibility. So all the standard modules that used Int for pointers/handles needed to be updated. If any of your code interfaces with such code, you'll need to adapt it. |
| ||
But new bmk.exe is intended to be compatible with vanilla, no? I thought before moving forward, I should put together a fresh vanilla build (but with new bmk) that works with my recent NG changes. I'm still hitting snags, though, the most recent being undefined references in pub.libpng. :/ ...brl.mod, pub.mod, and maxgui.mod are all vanilla, HOWEVER, I am using new bmk and MinGW 5.1... |
| ||
But new bmk.exe is intended to be compatible with vanilla, no? Yes, but that is just a tool like "make". I suppose "bmk" short for "blitzmax make" or something? undefined references in pub.libpng Is this the official one? The only thing I can think is that you are linking to other modules/files (perhaps your own) that have not been rebuilt properly (if they were the same files you were compiling with NG). |
| ||
Is this the official one? Yes, it is. you are linking to other modules/files (perhaps your own) that have not been rebuilt properly That's what I thought, too, but I've been double-checking them one by one. I'll keep working on it.I do have a vanilla backup where everything is working, but I really don't want to move forward with two code bases! |
| ||
bmk doesn't do anything clever. If you build it multi-threaded and you have a multi-core machine, it is very much more efficient at building things. Otherwise, you should end up with the same binary at the end of your build as you would with the standard bmk. |
| ||
Seems to be a problem in MaxGui in win32maxguiex.bmx line 288. Argument #1 is "Long" but declaration is "Byte Ptr." Not sure what is to be done with it. -w suppresses it, but could it be an issue? My NG test app now pops up a window, but fails very quickly. It looks like this might take a lot of effort to debug. :( Each of my modules publishes lua functions using ffi. Most of that glue code is generated procedurally. I wouldn't be surprised if that interferes with things that NG is doing (like generating function names) or vice versa. Then again, it could be something else entirely. EDIT: My NG-ified modules were fine all along. The problem (with compiling in vanilla) was because I copied over the NG version of zeke's luajit module and forgot a couple of small changes I'd made. Vanilla compilation of the NG modules now works. Still having issues with pure NG, though. Think it might have something to do with win32maxguiex... |
| ||
Well, I'm still not sure what's happening. I've tracked the problem to a specific line that is calling an external c function. The c function is part of my luascript module and all it does is return an array's type. I'm using that information to push the array to the lua stack. The weird part is that when I step through and reach that line, there's no indication that it's failing. It just takes me to a seemingly unrelated piece of code (in win32maxguiex) that is ClassWndProc. Seems to be caught in an infinite loop or something, but it works fine in vanilla BMX. |
| ||
One issue (sort of) resolved, for now. In order to push arrays to the lua stack, I needed to get the array type. AFAIK, vanilla Blitz has no built-in way of doing this, so I was using a C function. The C function was not compatible with the way NG is doing things, so I replaced it with a Blitz version that works, though it's a little slower. There seems to be some difference in the way NG handles Byte Ptr or Varptr. Admittedly, I'm a little fuzzy on the difference between the two. In some cases, they seem interchangeable. Anyway, a line that works fine in vanilla gives the following error in NG: Debugger Error:Invalid scope kind The odd thing is that here's the line where it happens: Local bp:Byte Ptr = Byte Ptr ci ..but if I comment it out, the following line works: Local p:ManaLink = ManaLink( GetBMaxObject( Byte Ptr ci + off ) ) That seems strange! code like this: Byte[]( GetBMaxObject( Byte Ptr ( ci ) + off ) )[ ary1 ] = mb ...is probably rather dangerous Hmm, I'm wondering if member offsets are handled differently in NG? More compact, perhaps? |
| ||
Bumping this with an example... This is extern.c ... #include <brl.mod/blitz.mod/blitz.h> // Get object at pointer. BBObject *GetBMaxObject( byte *bp ) { return *(BBObject**) bp; } This is test.bmx ... Import "extern.c" Extern "C" Function GetBMaxObject:Object( bp:Byte Ptr ) EndExtern Type manalink Field fo:Object EndType Type test Field fi:Int Field ff:Float Field fl:manalink EndType Local ml:manalink = New manalink Local t:test = New test t.fl = ml Local off:Int = 8 Local bp:Byte Ptr = Byte Ptr t Local pl:manalink = manalink( GetBMaxObject( bp + off ) ) 'EXPECTING: pl == ml == t.fl DebugStop The last assignment (pl) should be the same as (ml) and (t.fl). This works in vanilla bmx, but causes an error in NG. The bp assignment fails, for one. There are possibly more issues, but this is a start. |
| ||
Error of your sample is the following:Building byteptr [ 45%] Compiling:extern.c /testcodes/extern.c:4:26: error: unknown type name ‘byte’ BBObject *GetBMaxObject( byte *bp ) { ^ Build Error: failed to compile (256) /testcodes/extern.c bye Ron |
| ||
Import "byteptr.c" Extern "C" Function GetBMaxObject:Object( bp:Byte Ptr ) EndExtern Type manalink Field fo:Object Field val:String = "test" EndType Type test Field fi:Int Field ff:Float Field fl:manalink EndType Local ml:manalink = New manalink ml.val = "dynamic" Local t:test = New test t.fl = ml Local off:Int = 8 Local bp:Byte Ptr = Byte Ptr t Local pl:manalink = manalink( GetBMaxObject( bp + off ) ) If pl Then Print "pl ok " + pl.val If Not pl Then Print "pl failed" 'EXPECTING: pl == ml == t.fl DebugStop byteptr.c #include <brl.mod/blitz.mod/blitz.h> // Get object at pointer. //BBObject *GetBMaxObject(byte *bp) { // return *(BBObject**) bp; //} //taken from brl.mod-NG/reflection.mod/reflection.c BBObject *GetBMaxObject( BBObject **p ){ return *p; } Output: Building byteptr [ 45%] Compiling:byteptr.c [ 99%] Processing:byteptr.bmx [ 99%] Compiling:byteptr.bmx.console.release.linux.x86.c [100%] Linking:byteptr Executing:byteptr pl ok dynamic Process complete I think Brucey will surely say something more useful for you, as NG allows for 64bit builds, with other sizes for numbers, so "+ 8" might better be replaced by something more dynamic (adding each's field-size to an offsetSum). bye Ron |
| ||
Thanks for your reply. I don't get that compile error - it just gives an Exception Access Violation when it runs. So the difference is in the C code, but I don't see why one should work and the other shouldn't. I'll give your version a try, though. :) "+ 8" might better be replaced by something more dynamic (adding each's field-size to an offsetSum) This is a test case. Of course I'm storing offsets and using field sizes. ;)-- EDIT: New code made no difference for me. Still get the Exception Access Violation. I was wondering - are you testing on an actual Windows 32-bit machine or using an emulator? |
| ||
I tested on Linux ... and adjusting "+8" with something wrong, I get an segfault, so I assumed it worked as it should. This happens with NG on XP 32Bit: Building byteptr [ 95%] Processing:byteptr.bmx [ 97%] Compiling:byteptr.bmx.console.release.win32.x86.s flat assembler version 1.69.14 (1915406 kilobytes memory) 3 passes, 2775 bytes. [100%] Linking:byteptr.exe Executing:byteptr.exe pl ok dynamic Process complete bye Ron |
| ||
On my machine, "pl ok dynamic" prints out and it SEEMS to work, but THEN I get the Exception Access Violation. I'm using Win7 32-bit and this happens in MaxIDE. EDIT: If I take the DebugStop out, the exception doesn't happen. Weird... |
| ||
There seems to be some difference in the way NG handles Byte Ptr or Varptr Byte Ptr <Object> should give a pointer to the first field in the object. VarPtr <Object> should give a pointer to the address of the object. (this was generating incorrectly in NG. Should be working now). Correct field offsets are available in NG via the class debug scope array. This is the same metadata that reflection uses. |
| ||
Byte Ptr vs Varptr - Thank you for the explanation, that makes sense. It also tells me that Varptr probably wasn't causing my problem, but if it led to a bug fix, great! :) What does "Debugger Error: Invalid scope kind" mean? The following code (using same .c as above) results in the error. If I take out the "DebugStop" - it seems to be okay. Import "extern.c" Extern "C" Function GetBMaxObject:Object( bp:Byte Ptr ) EndExtern Type TOBJ EndType Type TA Field o:TOBJ EndType Type TT Method CD( ci:TA ) Local bp:Byte Ptr = Byte Ptr ci Local o:TOBJ = TOBJ( GetBMaxObject( bp ) ) DebugStop EndMethod EndType Local a:TA = New TA a.o = New TOBJ Local t:TT = New TT t.CD( a )Of course, I'm using the DebugStop to verify the value of 'o.' |
| ||
I've fixed a debugger issue, which should clear up that "invalid scope kind" message. |
| ||
Hmm, still happens with my project, but no longer with this example (still getting EAV with the DebugStop, though). Only change was to brl.appstub? I assume this error is supposed to occur under some circumstance..? EDIT: On a hunch, I tried something... I was expecting this... Local bp:Byte Ptr = ci bp = bp + 4 To have the same result as this. Local bp:Byte Ptr = Byte Ptr ci But it seemed to cause that "invalid scope kind" message. Still happens, so I changed the 4 to 8... bp = bp + 8 And that works! So I'm guessing there's some alignment issue? I would expect bp:Byte Ptr = Byte Ptr ci to always return that first field pointer, as you said. Sometimes (not always) it is off by 4. |
| ||
In this particular case, the "invalid scope kind" was caused by the debugger trying to determine the variable type of "bp". It does this by testing if the pointer is "GC valid". In this case, "bp" is pointing to a location inside an object, so in effect the answer from the check is "yes, this is a GC valid location". Unfortunately, "bp" is not a real object, but a pointer to the location of one. Think of it like a false-positive :-) I added some additional validation into bbGCValidate() but obviously it wasn't very effective at catching the issue. I need to have a look at either the way the debugger is handling variables, or improve the validation code. This issue only occurs when you are messing around with pointers of objects in debug mode. |
| ||
I had another go at it. Maybe it will work better now. So I'm guessing there's some alignment issue? There's no alignment issue with the generated code. There may be alignment issues with your assumption of offset values, but I don't recommend this way of digging into the objects anyway. So YMMV... There's debugscope/metadata stored already for each type that you can use to look up fields and so forth - it's what the reflection stuff uses to resolve them. It's a much cleaner way of accessing these things, I think. |
| ||
There may be alignment issues with your assumption of offset values Uh, nope - I was referring to the line "Local bp:Byte Ptr = Byte Ptr ci" which was ALWAYS adding 4. I could see it happen in MaxIDE's debugger right before it crashed and printed out the "invalid scope kind" message. The other lines were just tests to see what would work...I will give the new version a try. |
| ||
ALWAYS adding 4 I mentioned this previously - Byte Ptr <object> will return a pointer to the first field in the object. The first field, for x86, is generally 4 bytes into the object. |
| ||
The first field, for x86, is generally 4 bytes into the object. Yes, and as I just mentioned, 8 is what worked in this case. I don't know why...And yes, I am open to the possibility that I'm misinterpreting something, somewhere. |
| ||
There's debugscope/metadata stored already for each type Are you referring to getting a TField and accessing its _index? I don't believe I've written anything about where my offsets are coming from.If you're talking about just using reflection directly to get values, in vanilla that's too slow. Perhaps that's not the case with NG, but right now I'm just moving things over. In vanilla, it all works rather nicely. If you're wondering what the point of this is...I want to be able to define types in a simple manner and have them be able to self clone and serialize (read and write) without writing additional code. Took some effort to get that to work properly. |
| ||
I want to be able to define types in a simple manner and have them be able to self clone and serialize (read and write) without writing additional code Make sure that extended types are handled properly base: Method clone() extended: Method clone() 'overridden Serialization: Brucey's Peristence.mod might help here too. If speed is an requirement, custom solutions might be better (within my modded Persistence.mod I check for "SerializeClassNameToString()" methods to see if that individual class contains an adjusted serialization/deserialization-method. Sorry for derailing ... back to your offset problems. couldn't you check whether your "byte ptr" returns the correct offset to something or not? Eg. by adding the analyzed object to another one - and then checking the offset from "parent to children" in Vanilla, and in NG? bye Ron |
| ||
Make sure that extended types are handled properly Yes, of course. The beauty of storing the offsets and cloning them directly is that it's quite zippy and there is seldom a need to override the clone method. Same thing goes for serialization.The other thing I didn't mention is that objects can be defined in Lua and the data access methods are virtually identical between Blitz-defined and Lua-defined, except the Lua instances build meta-tables for faster JIT. Couldn't you check? Maybe, but I figured if Byte Ptr ci wasn't giving me the correct result, it was something that NG needs to deal with.EDIT: Just realized bp + 8 didn't crash, but it's NOT actually doing what I expect, either. Still trying to figure that out. |
| ||
Clone Method: this is like copying reference handles - it does not call "clone()" on child objects which are not "base objects" (int, string, ...). So cloning a "sprite" is maybe more a "copy content to another image". @byte ptr ci Yes, just assumed that it might help to see if there is a discrepance or not. Am sure that you both will tinker it out really soon. Glad I am not the only one coming up with "rare bugs" :-) bye Ron |
| ||
Not following you on clone method - is there something built in to BMX now? I thought it would do whatever you tell it to do... My Clone method always makes a deep copy of the object. It's not just a pointer or reference. Incidentally, I'm pretty sure I wrote this system before Brucey's persistence mod existed. EDIT: New version does seem to get further... |
| ||
@ deep copy Ok, so you handle "copying" of elements already (so the "image" of a cloned object is showing the same content, but is having its own pixmap-data) - this is what I wanted you to keep in mind (as it creates a lot of hassle if missed ;-)). Feel free to elaborate about in in an extra post (programming section), maybe it is of interest for some of us (at least me - as long as I understand it (a bit)). bye Ron |
| ||
I thought the programming section was for questions, not me blathering on... ;) This system is for Mana objects only - does not necessarily apply to pixmaps. However, it's pretty simple. The user defines an object, along with some extra meta-like data. A field containing another object can be defined as "connected to" or "pointing to" and that changes whether it clones its data or merely points to it. Same thing goes for when data is written. If it's "connected," it writes all of that object's data. If it's "pointed," it writes out the path only. So, something like a pixmap that is part of say, a texture, would probably be pointed to and would therefore not get copied UNLESS there was a method explicitly for that purpose. Textures are generally instanced, after all. I'm actually in the middle of writing this up and putting together a pitch for a game - perhaps I'll post a link later. :) |
| ||
Ahh thanks for that small insight. So it is kind of the "foreign key" in SQL. While "A links to B, C links to B" is working nicely there, how to post changes in "B" to all ones, using it? (A knows B, C knows B, but B does not know A or C). You could use some kind of "event propagation" (just telling the world, you changed a property) but this might be overhead - depending on the object's structure. Else you could store a "pointed from"-list for each property. Very memory consuming. Wasn't there something like "signals" in QT ... am sure others have tinkered with that problem too. But regardless of my questions I better wait for your thread (maybe a write a "PR"-one, and a "tech"-one) as I try to not further derail the thread (albeit I am interested in that subject ... argh ;-)) bye Ron |
| ||
You know that the generated source is there for you to examine yourself? For example: Type TA Field o:TOBJ EndType becomes something like struct _m_test_TA_obj { struct BBClass__m_test_TA* clas; struct _m_test_TOBJ_obj* __m_test_ta_o; }; So that Byte Ptr <instance of TA> will return a pointer which is essentially the address of TA plus the offset to the field __m_test_ta_o. Actual offsets depend on the architecture you are building against. Are you referring to getting a TField and accessing its _index? I'm referring to the generated C code, which has things like this, stored directly in the "class" which is the first part of your object structure above: struct BBDebugScope_2 _m_test_TA_scope ={ BBDEBUGSCOPE_USERTYPE, "TA", { { BBDEBUGDECL_FIELD, "o", ":TOBJ", .field_offset=offsetof(struct _m_test_TA_obj,__m_test_ta_o) }, { BBDEBUGDECL_TYPEMETHOD, "New", "()", &__m_test_TA_New }, BBDEBUGDECL_END } }; This is what reflection uses to build up a picture of your type. |
| ||
is there for you to examine Yes, I am aware of that. I looked through it before and hastily concluded it was hard to read, but I've changed my mind. :)The latest NG is no longer giving me the "invalid scope kind" message, but it's still hanging and worse, it's really hard to find out where exactly because there must be some state that it's getting into that causes the next DebugStop, wherever that may be, to fail. Yes, I know - MMMV. --- EDIT: I've just confirmed that... Local bp:Byte Ptr = ci Local bpp:Byte Ptr = Byte Ptr ciBoth of these yield the same memory address in vanilla BMX, but in NG, bpp = bp + 4. Is that difference intentional? |
| ||
to not further derail the thread It's just you and Brucey and me here. Only danger is Brucey abandoning this thread out of boredom. ;)Anyway, the problem you mentioned isn't handled. Changing "B" would not notify "A" or "C" - you're right, keeping a list would be massive overhead. |
| ||
Aha!! I noticed there was a new version of bcc and tried it. Whaddya know, it works 100% now! Thanks, Brucey! :) |
| ||
According to the size of changes the fix must have been found very quick ;-)). wondering what other bugs are waiting to get exposed. Bye Ron |
| ||
According to the size of changes the fix must have been found very quick Haw haw... :-p |
| ||
Another one? This works... Local bp:Byte Ptr = Byte Ptr ci Int Ptr( bp )[off] = i This doesn't... Int Ptr( Byte Ptr ci )[off] = i I can live with doing things the first way, but why wouldn't the second work? Of course, same for Float, Long, etc. --- EDIT: Okay, now this is fixed, too. Thanks! |