Ran into the ReferenceTable limit in my Android jni function. Cleaned it up with DeleteLocalRef, but I want to know if I should do the same for the arguments passed to the function from Java. Is it possible? If so, is it worthwhile?
Local references are created within a native method only. I dont think it is worthwhile doing that for the function arguments. Best practice will be to delete the local references if you are doing anything in a loop, or creating a lot. Take a look at sun's reference
Related
Suppose I'm using JNI to call some Java method that returns String, i. e. jstring in native code:
jstring jStr = (jstring)env->CallStaticObjectMethod(myApplicationClass, getString);
Do I then need to call env->DeleteLocalRef(jStr)? I think I do, but I can't find any specific instructions that state so in the JNI reference, and I can see I have a lot of code that doesn't call it - tried and true code. But if there was a minor memory leak, no one would notice since this code doesn't create many objects.
Every local reference you create is automatically freed when your JNI-called function returns to Java.
The JNI specification outlines two cases where you might want to use DeleteLocalRef:
A native method accesses a large Java object, thereby creating a local reference to the Java object. The native method then performs
additional computation before returning to the caller. The local
reference to the large Java object will prevent the object from being
garbage collected, even if the object is no longer used in the
remainder of the computation.
In other words, if you allocated a multi-megabyte string and no longer need it, you can delete the reference immediately, instead of leaving it to the JVM when you return to it. However, this is only useful if you need to perform additional steps in the JNI world before returning.
Note that this situations talks about a JNI function that is called from Java.
By attaching native threads to the JVM you can end up in the reverse situation, where your native code calls into the JVM. In that situation the JVM will not auto-free your local references and you need to delete local references yourself.
As a concrete example of that case, all the local references created in this function in the JNI cookbook will linger; they are never cleaned up manually.
A native method creates a large number of local references, although not all of them are used at the same time. Since the VM needs
a certain amount of space to keep track of a local reference, creating
too many local references may cause the system to run out of memory.
For example, a native method loops through a large array of objects,
retrieves the elements as local references, and operates on one
element at each iteration. After each iteration, the programmer no
longer needs the local reference to the array element.
This one is simpler: there is an upper limit to the number of local references.
Yes you must dispose the local references returned by Java callbacks. The standard rules apply: instead of DeleteLocalRef(), you can use PushLocalFrame()/PopLocalFrame(), or the local reference will be released automatically when the thread is detached from JVM, or the native method returns to Java (if this happens inside a native method).
Is it possible that luabind checks, if a member function call to an exported class (object) is for a valid object?
lets assume that i have a Class called Actor exposed using luabind to lua. Im calling a lua function from C++ with an actor object as parameter. Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.
Later on, the actor object is deleted from the C++ site, another function is called which tries to access the invalidated actor object (any method from it) - and obviously since it has been deleted, it results in a crash (access violation)
sample:
local myObjRef = nil
function doSomethingWithActor(actor)
-- save, still valid object
actor:Say("hello")
myObjRef = actor
end
function calledAfterActorWasDeleted()
--- will crash if the c++ object has been deleted meanwhile, works fine if it still exists
myObjRef:Say("Crash...")
end
A NIL check doesnt help here, is this something that can be checked on luabinds site? The functions are executed using lua_pcall(....) and the stacktrace shows the error at luabinds call.hpp results = maybe_yield(L, lua_gettop(L) - arguments, (Policies*)0);
If not, is there another solution how to make sure somebody who writes a script cannot create these issues?
Now before the function finishes, a script write would put the actor object in a global lua reference to be accessed later.
That right there is where your problem is coming from. If you want Lua code to own the object (that is, preserve the existence of this object), then you need to use Luabind mechanics to tell Luabind that you want to do that. Otherwise, if you pass a pointer to some Lua function, Luabind will assume that the function will not be trying to gain ownership of it.
If you want ownership to be shared between Lua and Luabind, then you should wrap your objects in a boost::shared_ptr, and use Luabind's smart pointer mechanisms to do this.
You could also simply segregate your scripts better. If you have some script that operates on a particular actor, then that script and any functions it contains should be destroyed (ie: lose all references to it) along with the object. This requires proper coding discipline on the C++ side. It will also require that you use Lua environments to properly encapsulate each instance of a script, so that they can't sneak things out via globals. Lastly, you will need to have C++ maintain total control over when scripts are called and when they aren't.
Otherwise, ownership is something your scripters are simply going to have to know about and be careful of. They can't treat C++ parameters like any old Lua value.
If exercising disciplined programming practice is not possible or practical for you, then you will simply have to not pass Lua the actual C++ object. Instead, you need to pass Lua some proxy object, which is a reference to the original. boost::weak_ptr is a good example of such an object (though you wouldn't pass it exactly to Lua). The proxy would forward calls to the actual object. If the object has been deleted, the proxy would detect this and fail or do nothing or whatever.
I solved my issue the following way:
When im about to delete an object, i iterate through all lua functions from C++ (i have them in a list, they are bound to specific actor objects each). Then i inspect each upvalue (global/local vars accessable to a function) - then i compare the userdata pointer with my object im about to delete - if they match (and their classes) and NIL the upvalue. Optionally, i could just remove that offending function because it would not work well anymore anyway.
So the next the time the function is called, im just getting a soft lua error "trying to access xxx a nil value..." - no more access violations.
I know people would say "dont use lua_getupvalue/lua_setupvalue - they are only for debugging!" - but there is actually no documented or spoken side effect - and in my case its perfectly safe and works well - also there isnt the issue with left over proxy objects i could not delete.
I'm implementing Lua scripting in my game using LuaBind, and one of the things I'm not clear on is the logistics of reloading the scripts live ingame.
Currently, using the LuaBind C++ class luabind::object, I save references to Lua callbacks directly in the classes that use them. Then I can use luabind::call_function using that object in order to call the Lua code from the C++ code.
I haven't tested this yet, but my assumption is that if I reload the scripts, then all the functions will be redefined, BUT the references to the OLD functions will still exist in the form of the luabind::object held by the C++ code. I would like to be able to swap out the old for the new without manually having to manage this for every script hook in the game.
How best to change this so the process works?
My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it. I'm looking for better ideas!
My first thought is to not save a reference to the function directly, but maybe save the function name instead, and grab the function by name every time we want to call it.
If your classes are calling global functions with known names, then that pretty much solves your problem. No need to grab a reference in advance; it's not going to make a measurable performance difference. I think call_function supports passing the function name as a string anyway, right?
You typically store reference to a function value when the Lua script is registering a callback. In that case, it's much better than storing a name, because it allows the Lua script to register functions which are local, anonymous, ect.
If you really had to grab the value value in advance, as you're doing now (and there's really no reason to do that, but we'll pretend it's necessary), I would add a layer of indirection. You could have a LuaFunctionReference class which encapsulates a global name. During instantiation, it grabs a reference to the function the global contains. These objects could be acquired from a factory which maintains a list of all such references. When you reload a script, you could have the factory/manager/pool/etc. object iterate through the references and have them update themselves, so all the references tucked away in classes throughout the system would be updated.
So, I'm using the FMOD api and it really is a C api.
Not that that's bad or anything. Its just it doesn't interface well with C++ code.
For example, using
FMOD_Channel_SetCallback( channel, callbackFunc ) ;
It wants a C-style function for callbackFunc, but I want to pass it a member function of a class.
I ended up using the Win32 trick for this, making the member function static. It then works as a callback into FMOD.
Now I have to hack apart my code to make some of the members static, just to account for FMOD's C-ness.
I wonder if its possible in FMOD or if there's a work around to link up the callback to a specific C++ object's instance member function (not a static function). It would be much smoother.
You cannot directly pass a member function. A member function has the implicit parameter this and C functions don't.
You'll need to create a trampoline (not sure the signature of the callback, so just doing something random here).
extern "C" int fmod_callback( ... args ...)
{
return object->member();
}
One issue is where does that object pointer come from. Hopefully, fmod gives you a generic context value that will be provided to you when your callback is made (you can then pass in the object pointer).
If not, you'll just need to make it a global to access it.
I guess it supposed to work like this:
You can assign some user data to channel by calling FMOD_Channel_SetUserData. This user data should be a pointer to your C++ object that handles events.
Then you should write C-style callback that extracts that object by calling FMOD_Channel_GetUserData and then calls your C++ instance method on that object.
There is a non-portable, and pretty hackish solution that has the advantage of at least being thread-safe, which the "trampoline" methods are not.
You can generate the actual function machine code on the fly. The basic idea is that you have a template for your call-back function that takes an object pointer and a member-function pointer and gives you a block of heap memory that you can pass to the library as a C call-back function, that will, when called, turn around and call the member function on that object.
It's messy, and you'll have to provide an implementation for any new platform (any time the calling convention changes), but it works, is thread-safe. (Of course you'll also have to watch out for DEP). The other thread-safe solution is to resort to thread-local storage (assuming that you know the call-back will happen on the same thread as the call you made).
See http://www.codeproject.com/KB/cpp/GenericThunks.aspx for an example of how you could go about generating thunks.
Using only a function pointer (and no additional separate object pointer) for a C callback is a broken design, in my humble opinion.
If the function were, instead, FMOD_Channel_SetCallback(channel, callbackFunc, callbackObj), then your static method just takes an instance of the object, then calls callbackObj->func() (which obviously can be non-static).
you need to use a trampoline and store the pointer to the object you want to get the member function called on in a global or static variable, i.e.
Object *x;
void callback_trampoline() { x->foobar(); }
...
FMOD_Channel_SetCallback(CHANNEL, callback_trampoline);
A while ago I read the Debugging Windows Programs book, and one of the tricks that it talked about extensively was calling functions from the Visual C++ debugger (quick)watch window.
As luck would have it, I don't have a copy on hand and the little documentation that I could find about this is really really poor.
So how DO you call a member function in the watch window? What if the function lives in a DLL? What if it is part of a namespace? Can you pass non-trivial parameters?
Let's use this example: I want to call the size() method of QList<MyType>, where MyType is a custom type.
Thanks!
It works and is hugely useful. You can evaluate expressions in the watch window or open the quick watch window (ctrl-alt-Q -- a very handy shortcut to know). It will let you call most forms of member functions. The only times it commonly tends to fail is if you've got overloaded operators, eg with smart pointers. For a simple class without overloaded operators you should find it should work well. I think it should accept non-trivial parameters (though obviously it depends how non-trivial!) As well as calling functions that return values, you can also call functions that modify the object -- there's no constraint on only calling getter methods.
The other kind-of-obvious thing to remember is that all variables are evaluated in the local stack frame, so ensure the variable is visible from the current point in the stack.
I'd say just write list.size() in the watch window, where list is an instance of your QList, but I'm not sure this works for all classes
Are you sure that you can call methods of objects while debugging code in Visual Studio? Because I was never able to do so. The closest debugging features I know is to have a quick watch on objects (including local objects in the stack, navigating through the call stack), or compile and continue (I used it in VC6) allowing to change the code, recompile and continue debuging from the last statement...