Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - ChronicRat

Pages: 1 2 [3] 4 5 ... 22
31
General / Re: What about memory leaks?
« on: June 03, 2015, 08:22:25 pm »
I dont delete objects from vector, so it should be leak there...
Yep, I didn't noticed it. So, there is only one thing left - you are not in DEBUG mode.

32
General / Re: What about memory leaks?
« on: June 03, 2015, 06:28:35 pm »
And change
#if defined(_DEBUG) && defined(WINDOWS)
to
#ifdef _DEBUG
I'm sure that you have no WINDOWS definition.

33
General / Re: AW: What about memory leaks?
« on: June 03, 2015, 06:26:29 pm »
At best you learn about RAII and smart pointers and stop worrying about memory leaks.
I think that newbie programmer must avoid use of smart pointers - he has to understand what they do. But he can read about RAII, sure.

34
General / Re: What about memory leaks?
« on: June 03, 2015, 06:23:02 pm »
In the very begining of "main" function! =) And it won't list leaks because your code hasn't them.

35
General / Re: What about memory leaks?
« on: June 03, 2015, 05:39:24 pm »
This is incorrect. You list leaks when your objects are alive.
Use this code in the very begining:
// enable memleak detection
#if defined(_DEBUG) && defined(WINDOWS)
        int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
        tmpFlag |= _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF;  // Check heap alloc and dump mem leaks at exit
        _CrtSetDbgFlag( tmpFlag );
        assert( !errno );
        //_crtBreakAlloc = 101;
#endif
 
This will autmatically list all the leaks on program exit.

36
Btw, object returned by (JNIEnv) GetObjectClass requires to delete local ref to it after use. Or you can get this error: "E dalvikvm: JNI ERROR (app bug): local reference table overflow (max=512)"
I just ran stress-test for previously posted VirtualKeyboard to initialize it per frame. So, we need to delete local reference to EVERY jobject (jclass, jstring, jarray) - CallObjectMethod, GetObjectClass, FindClass... for all of them.
I updated post with VirtualKeyboard class. There are fixed leaks of local refs. Pay attention to other way to get unicode value. I think it is better (no proofs =)).

37
About this part of code:
        // This requires some special treatment, since this might represent
        // a repetition of key presses or a complete sequence
        if (key == AKEYCODE_UNKNOWN)
        {
            // This is a unique sequence, which is not yet exposed in the NDK
            // http://code.google.com/p/android/issues/detail?id=33998
        }
 
In this case you have to return value as Unhandled event. This will allow to catch this event in Java and use "KeyEvent.getCharacters" method. Now your "handled" variable is always set to 1, and user can't catch this event in "dispatchEvent" method.

38
For example, how to use JNI a little bit faster and much more safer or vice versa =) (based on SFML "setVirtualKeyboardVisible"):
#ifndef _ANDROID_VIRTUAL_KEYBOARD_H_
#define _ANDROID_VIRTUAL_KEYBOARD_H_



#include <jni.h>



class VirtualKeyboard
{
public:
        VirtualKeyboard();
        explicit VirtualKeyboard(JavaVM* vm, jobject activityObject);
        ~VirtualKeyboard();

        void Init(JavaVM* vm, jobject activityObject);
        bool SetVisible(bool b) const;
        int GetUnicodeValue(int deviceId, int keyCode, int meta) const;

private:

        void Clear();

        JavaVM*         m_JavaVM;
        jobject         m_InputMethodManager;
        jobject         m_DecorView;
        jclass          m_KeyCharacterMapClass;
        jmethodID       m_HideSoftInput;
        jmethodID       m_ShowSoftInput;
        jmethodID       m_GetWindowToken;
        jmethodID       m_LoadKeyMap;
        jmethodID       m_KeyMapGet;
};


#endif // _ANDROID_VIRTUAL_KEYBOARD_H_
 

Implementation:

#include "virtual_keyboard.h"
#include <android/native_activity.h>



static const char* CONTEXT_PATH = "android/content/Context";
static const char* INPUT_METHOD_MANAGER_PATH = "android/view/inputmethod/InputMethodManager";
static const char* WINDOW_PATH = "android/view/Window";
static const char* VIEW_PATH = "android/view/View";
static const char* KEY_CHARACTER_MAP_PATH = "android/view/KeyCharacterMap";



VirtualKeyboard::VirtualKeyboard():
        m_JavaVM(NULL),
        m_InputMethodManager(NULL),
        m_DecorView(NULL),
        m_KeyCharacterMapClass(NULL),
        m_HideSoftInput(0),
        m_ShowSoftInput(0),
        m_GetWindowToken(0),
        m_LoadKeyMap(0),
        m_KeyMapGet(0)
{
}



VirtualKeyboard::VirtualKeyboard(JavaVM* vm, jobject activityObject):
        m_JavaVM(NULL),
        m_InputMethodManager(NULL),
        m_DecorView(NULL),
        m_KeyCharacterMapClass(NULL),
        m_HideSoftInput(0),
        m_ShowSoftInput(0),
        m_GetWindowToken(0),
        m_LoadKeyMap(0),
        m_KeyMapGet(0)
{
        Init(vm, activityObject);
}



VirtualKeyboard::~VirtualKeyboard()
{
        Clear();
}



void VirtualKeyboard::Clear()
{
        if (!m_JavaVM)
        {
                return;
        }

        JNIEnv* env = NULL;
        Java::Thread attach(m_JavaVM, env);
        env->DeleteWeakGlobalRef(m_InputMethodManager);
        env->DeleteWeakGlobalRef(m_DecorView);
        env->DeleteWeakGlobalRef(m_KeyCharacterMapClass);
        m_JavaVM = NULL;
        m_InputMethodManager = NULL;
        m_DecorView = NULL;
        m_KeyCharacterMapClass = NULL;
        m_HideSoftInput = 0;
        m_ShowSoftInput = 0;
        m_GetWindowToken = 0;
        m_LoadKeyMap = 0;
        m_KeyMapGet = 0;
}



void VirtualKeyboard::Init(JavaVM* vm, jobject activityObject)
{
        if (m_JavaVM)
        {
                Clear();
        }

        if (!vm || !activityObject)
        {
                return;
        }

        m_JavaVM = vm;
        JNIEnv* env = NULL;
        Java::Thread attach(m_JavaVM, env);
        jclass activityClass = env->GetObjectClass(activityObject);
        jclass contextClass = env->FindClass(CONTEXT_PATH);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jfieldID fieldINPUT_METHOD_SERVICE = env->GetStaticFieldID(contextClass,
                "INPUT_METHOD_SERVICE", "Ljava/lang/String;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jobject INPUT_METHOD_SERVICE = env->GetStaticObjectField(contextClass,
                fieldINPUT_METHOD_SERVICE);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(contextClass);

        jclass inputMethodManagerClass =
                env->FindClass(INPUT_METHOD_MANAGER_PATH);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jmethodID getSystemServiceMethod = env->GetMethodID(activityClass,
                "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jobject inputMethodManagerObject = env->CallObjectMethod(activityObject,
                getSystemServiceMethod, INPUT_METHOD_SERVICE);
        env->DeleteLocalRef(INPUT_METHOD_SERVICE);

        jmethodID getWindowMethod = env->GetMethodID(activityClass,
                "getWindow", "()Landroid/view/Window;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(activityClass);

        jobject windowObject = env->CallObjectMethod(activityObject, getWindowMethod);

        jclass windowClass = env->FindClass(WINDOW_PATH);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jmethodID getDecorViewMethod = env->GetMethodID(windowClass,
                "getDecorView", "()Landroid/view/View;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(windowClass);

        jobject decorViewObject = env->CallObjectMethod(windowObject, getDecorViewMethod);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(windowObject);

        jmethodID showSoftInputMethod = env->GetMethodID(inputMethodManagerClass,
                "showSoftInput", "(Landroid/view/View;I)Z");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jclass viewClass = env->FindClass(VIEW_PATH);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jmethodID getWindowTokenMethod = env->GetMethodID(viewClass,
                "getWindowToken", "()Landroid/os/IBinder;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(viewClass);

        jmethodID hideSoftInputMethod = env->GetMethodID(inputMethodManagerClass,
                "hideSoftInputFromWindow", "(Landroid/os/IBinder;I)Z");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);
        env->DeleteLocalRef(inputMethodManagerClass);

        jclass keyCharacterMapClass = env->FindClass(KEY_CHARACTER_MAP_PATH);
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jmethodID loadMethod = env->GetStaticMethodID(keyCharacterMapClass,
                "load", "(I)Landroid/view/KeyCharacterMap;");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        jmethodID getMethod = env->GetMethodID(keyCharacterMapClass,
                "get", "(II)I");
        JAVA_EXCEPTION_CHECK_AND_DO(env, m_JavaVM = NULL; return);

        m_InputMethodManager = env->NewWeakGlobalRef(inputMethodManagerObject);
        env->DeleteLocalRef(inputMethodManagerObject);
        m_DecorView = env->NewWeakGlobalRef(decorViewObject);
        env->DeleteLocalRef(decorViewObject);
        m_KeyCharacterMapClass = (jclass) env->NewWeakGlobalRef(keyCharacterMapClass);
        env->DeleteLocalRef(keyCharacterMapClass);
        m_HideSoftInput = hideSoftInputMethod;
        m_ShowSoftInput = showSoftInputMethod;
        m_GetWindowToken = getWindowTokenMethod;
        m_LoadKeyMap = loadMethod;
        m_KeyMapGet = getMethod;
}



bool VirtualKeyboard::SetVisible(bool b) const
{
        if (!m_JavaVM)
        {
                return false;
        }
        JNIEnv* env = NULL;
        Java::Thread attach(m_JavaVM, env);
        bool res = false;
        int flags = 0;

        if (b)
        {
                res = env->CallBooleanMethod(m_InputMethodManager,
                        m_ShowSoftInput, m_DecorView, flags);
        }
        else
        {
                jobject binderObject = env->CallObjectMethod(m_DecorView,
                        m_GetWindowToken);
                res = env->CallBooleanMethod(m_InputMethodManager,
                        m_HideSoftInput, binderObject, flags);
                env->DeleteLocalRef(binderObject);
        }
        return res;
}



int VirtualKeyboard::GetUnicodeValue(int deviceId, int keyCode, int meta) const
{
        if (!m_JavaVM || keyCode == 0)
        {
                return 0;
        }
        JNIEnv* env = NULL;
        Java::Thread attach(m_JavaVM, env);
        jobject kcmObject = env->CallStaticObjectMethod(m_KeyCharacterMapClass, m_LoadKeyMap, deviceId);
        JAVA_EXCEPTION_CHECK_CONTINUE(env);

        if (!kcmObject)
        {
                return 0;
        }

        int unicode = env->CallIntMethod(kcmObject, m_KeyMapGet, keyCode, meta);
        JAVA_EXCEPTION_CHECK_CONTINUE(env);
        env->DeleteLocalRef(kcmObject);
        return unicode;
}

 

And you have to call Init function each time "ANativeActivity_onCreate" called.

39
I just started to work hard with JNI at my job two monthes ago. =) Btw, it is useful to create RAII class to attach Java thread (so we need JavaVM only, pointer to JNIEnv we'll receive after attaching to the thread). And check for exceptions after retreiving of method ids or classes.
I use macros for it:
#define JAVA_EXCEPTION_CHECK_AND_DO(env, doNext)\
                if (env->ExceptionCheck())\
                {\
                        jthrowable throwable = env->ExceptionOccurred();\
                        if (throwable != NULL)\
                        {\
                                Java::LogException(env, throwable);\
                                doNext;\
                        }\
                }
This allow us to not to crash each time if something goes wrong with Java.

Class for attach to Java thread:

namespace Java
{

class Thread
{
public:

        explicit Thread();
        explicit Thread(JavaVM* jvm, JNIEnv*& env);
        ~Thread();

        void Attach(JavaVM* jvm, JNIEnv*& env);
        void Detach();
        bool IsAttached() const { return m_Attached; }

private:

        bool            m_Attached;
        JavaVM*         m_JavaVM;
};

} // namespace Java
 

Implementation:
namespace Java
{

Thread::Thread():
        m_Attached(false),
        m_JavaVM(NULL)
{
}



Thread::Thread(JavaVM* jvm, JNIEnv*& env):
        m_Attached(false),
        m_JavaVM(NULL)
{
        Attach(jvm, env);
}



void Thread::Attach(JavaVM* jvm, JNIEnv*& env)
{
        assert(jvm);
        assert(!m_Attached && "Must be detached before call this function!");
        m_JavaVM = jvm;
        int status = m_JavaVM->GetEnv((void **)&env, JNI_VERSION_1_6);

        if (status == JNI_EDETACHED)
        {
                jint res = m_JavaVM->AttachCurrentThread(&env, NULL);
                m_Attached = res == JNI_OK;
        }
}



Thread::~Thread()
{
        Detach();
}



void Thread::Detach()
{
        if (m_Attached)
        {
                m_Attached = false;
                jint res = m_JavaVM->DetachCurrentThread();
                assert(res == 0);
        }
}

} // namespace Java
 

Using:
JNIEnv* env = NULL;
Java::Thread attach(m_JavaVM, env);
env->FindClass(....
 
And we don't bother where to exit from the function.

And another one note: use variables to hold method ids or java classes. It will improve performance greatly.

40
About WindowImplAndroid::getUnicode.
There new Java object is created and I think it can cause Java stackoverflow without delete of local reference.
Add    lJNIEnv->DeleteLocalRef(ObjectKeyEvent); before detach of Java thread.
You have to delete local refs manually for all created Java objects, even strings.

41
std::queue is a thin wrapper over a container and unfortunately it is not useful as a queue most of the time.
Hm, I use std::queue as queue two years already. And I can't imagine another way to use std::queue except queue. =)

42
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 08, 2015, 03:04:58 pm »
It looks like you just never met ugly code. =) And Lua code by Elias Daler is really good.

43
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 08, 2015, 06:43:55 am »
Do you actually find Lua beautiful?
What else could be simpler, smaller and faster? Lua is ideal! =)

44
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 07, 2015, 12:27:48 pm »
Lua is beautiful. Do you use some sort of OOP realisation under Lua or only table like these?

45
SFML projects / Re:creation - a top down action rpg about undeads
« on: May 04, 2015, 11:11:47 am »
Cool, I don't like "pixel" styled games but this one is really fun.

Pages: 1 2 [3] 4 5 ... 22