I am converting someones Palm Pilot code into an Android application for them. This involves me using the NDK to read from one of their already built libraries. For this, I need to create several new functions.
void __stdcall FreeRelay(void){
RelayAPI_DataValid=0;
RelayAPI_SetBaud=0;
RelayAPI_get=0;
RelayAPI_put=0;
RelayAPI_flush=0;
RelayAPI_delay=0;
RelayAPI_initilized=0;
}
void Java_my_MainMenu_FreeRelayJava( JNIEnv * env, jobject this ) {
RelayAPI_DataValid = 0;
RelayAPI_SetBaud = 0;
RelayAPI_get = 0;
RelayAPI_put = 0;
RelayAPI_flush = 0;
RelayAPI_delay = 0;
RelayAPI_initilized = 0;
}
Now, my error is in the last line of the second method. I had originall had it spelled RelayAPI_initialized, I know that thats correct, but I'm not going through the trouble of changing all of this C code for the typo. I'll make my function fit with the old code. Anyway, I tried ndk-build and got this.
Now in between those separate ndk-build calls, I fixed the error. But it still is telling me in line 615 there is an error dealing with RelayAPI_initialized but its NOT THERE. I don't know whats going on, and I really know very little about C. I saved my files with the updated information then called ndk-build. WHAT AM I MISSING?
maybe you can grep to find if other var like RelayAPI_* are defined GLOBALLY in some c code or header file.
if not, define it, or don't set it.
it will resolve compilation error... but probably it wont work
do a clean of your build. so the party built stuff is deleted and you get a full rebuild.
Related
Im building a project that needs to modify the behavior of some bionic methods (e.g getaddrinfo, __android_print). I've been able to create the hooked library both using a standalone compiler or including it directly in the Apk using Cmake. I've been able to preload the shared library using setprop wrap.com.foo.bar and LD_PRELOAD, and it is working and I get the result I want. However, I want to preload the hooked library programatically so I dont need to go through the specific steps of LD_PRELOAD (a.k.a disable SELinux, root device, setprop), every time after rebooting a device.
I tried using
// MainActivity
companion object {
System.load("/data/data/com.foo.bar/lib/libhookedmethod.so")
}
But I don't see the method being replaced.
As a reference, the hooked method is rather simple. Here's an extreme simplification:
int __android_print(varargs a) {
int realmethod(...);
realmethod = dlsym("__android_print");
doStuff();
int res = realmethod(a) ;
return res;
}
Again, compiling and using LD_PRELOAD works, but I want to achieve it without using LD_PRELOAD...
Anything helps! Thanks in advance
The LD_PRELOAD works by asking the dynamic loader to load referenced library before any other. The loader resolves references to a given symbol by searching loaded libraries in their load order.
Once a symbol is resolved to a particular library, it will not be rebound to some other library for the duration of this process.
Above explanation should make it obvious why loading libhookedmethod.so after the program is already running has no effect.
About the only way you can achieve what you want is to setenv() (if not already set) and re-exec() the current process. Something like this:
int main(int argc, char *argv[])
{
char *e = getenv("LD_PRELOAD");
if (e == NULL || /* any other checks that show LD_PRELOAD to not be as we want it */) {
setenv("LD_PRELOAD", ..., 1);
execvp(argv[0], argv);
}
// LD_PRELOAD is to our liking. Run the actual program.
...
}
When I attempt to deploy my app using Eclipse it throws FileNotFoundException on my font, which I've now copied to both the assets/src and assets directory to be doubly sure.
I had this problem before, after succesfully integrating SDL_ttf into my Visual C++ build of the same app and transferring across to Eclipse for Android. Now I'm facing it again I thought I better write about it. The SDL_ttf source comes with a freetype folder already in place and referenced by android as external/freetype-2.4.12. DinoMage states I need to download this separately although he refers to freetype-2.4.11 being the latest. That's the only obvious difference from my VC build, apart from minor compiler intolerances.
I've got it working a bit now. I can sign the app (unsigned didn't work), disable USB debugging, and it will load the font and display a menu. From there it breaks, again, so I can't see how I'm supposed to debug it further. I'm sure I'll fix it somehow. But I'll also forget the obscura if I don't post here.
I don't know much about using the debugger with Android, but I can make suggestions otherwise.
Is your assets path really named "assetts"? If possible, I'm not sure how one would get Android and SDL to look there instead of "assets".
SDL and it's friend libs like SDL_ttf search for files local to the assets directory first and then search relative to the root directory. So I would expect that your "res/stubbornFont.ttf" will never load because it is in the resources "res" directory and SDL_ttf will not look there.
Maybe you can specify it relative to assets/, like "../res/stubbornFont.ttf", but I haven't tested that. It would work if you put the font in assets/ and loaded it as "stubbornFont.ttf".
I've think I've got closure on this.
It is possible to debug the app. By continuing it will trap several times trying to load one font. I think it stops eventually, I'm not sure. I've stepped through it from where it lands me at the throw stage. However single stepping from there begins from the synchronized statement, sorry it's Java but from my quick reference to What does 'synchronized' mean? I think this is a race condition
public final AssetFileDescriptor openFd(String fileName)
throws IOException {
synchronized (this) {
if (!mOpen) {
throw new RuntimeException("Assetmanager has been closed");
}
ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets);
if (pfd != null) {
return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]);
}
}
throw new FileNotFoundException("Asset file: " + fileName);//DEBUGGER traps here
}
You might be there all day single stepping that! It appears to perform all steps required of it and finally I land in:
public static ReadableByteChannel newChannel(InputStream inputStream) {
return new InputStreamChannel(inputStream);
}
No, not finally, lastly, there is
public static Context getContext() {
return mSingleton;
}
In the SDLActivity I extend.
That has a bunch of members I don't want to know about:
Luckily I discovered I can selectively "Disconnect" using a button in eclipse two along from debug/run. It has no keyboard shortcut and I'm not sure why but it will reconnect when I next trigger an exception. This is debugging as I know and love it in Android and Eclipse, still probably easier than GDB.
For arguments sake I've even replaced:
//TTF_Font *gFont = TTF_OpenFont( "res/stubbornFont.ttf", 160 );
with
TTF_Font *font=TTF_OpenFontRW(SDL_RWFromFile("res/stubbornFont.ttf", "rb"), 1, 160);//Same difference
UPDATE/EDIT
Here is the solution I was really looking for,
turning off uncaught exceptions in eclipse, it really is just that, Window->Preferences->Java->Debug and it's the very first box at the top for me.
Maybe it's my configuration problem but... My Eclipse shows error when i'm trying to do sth like this:
// let say that i have a vector like this:
std::vector<Point2f> someVec(/*init vector or sth...*/);
and i want to read a field or whatever like this:
someVec[0].x = 10;
but then Eclipse cry that it's error - x is not a property. Moreover sth like this is "invalid" too:
// both are 'invalid'
someVec.operator[](0);
// or
someVec.at(0);
On the other hand I can do sth like this and now Eclipse doesn't see any problem:
Point2f& p = someVec[0];
p.x = 10;
This 'hack' works well:
someVec.data()[0].x;
Have ever had similar problem maybe?
I found an answer. I included stddef.h which define size_t and some other stuff. Now problem is solved.
I'm porting a simple tetris-like XNA app to Android, using Mono For Android and MonoGame; I have followed the suggested steps in this link and so far, everything compiles well, and no relevant warnings fire up. However, upon loading the contents, a null parameter exception breaks the program at the point below in my program:
protected override void LoadContent() {
// ...
_font = Content.Load<Microsoft.Xna.Framework.Graphics.SpriteFont>("SpriteFont1");
// ...
}
The content root directory is set in the game constructor class:
public Game2 (){
Content.RootDirectory = "Content";
Content.RootDirectory = "Assets/Content"; // TEST.
//...}
And I have tried several combinations, all to no avail.
I have also tried setting the xnb files as Content as well as Android Assets in the Build Action property; having the linked, copied always, copied only if newer... etc.
Either way, my problem is that I don't really understand WHY and HOW should I do this. I'm rather new to the platform and to XNA as well, so this may very well be a newbie question, but the truth is after several hours banging my head and fists against the monitor/keyboard I feel stuck and need your help.
I have a library that supports variable-width fonts (generated by BMFont) on MonoGame. Unfortunately it is a renderer and so has other code around it. However, the basic idea is very simple. You can take a look at the loader here and the mesh builder (given a string) here. This builder supports fonts that spread characters across multiple pages, too.
Hope this helps!
MonoGame (2.5.1) throws NotImplementedException in ContentManager.Load for SpriteFont type. Have the same not resolved problem. I'm trying not to use DrawString.
For loading textures in Win32 application I use:
Content.RootDirectory = #"../../Content";
var sampleTexture = Content.Load<Texture2D>("Sample.png");
You even must not add it to solution.
For Andoind (MonoDroid) application you must add "Content" folder to your solution and set "Andtoid Asset" in "Sample.png" properties.
Content.RootDirectory = "Content";
var sampleTexture = Content.Load<Texture2D>("Sample.png");
See also:
http://monogame.codeplex.com/discussions/360468
http://monogame.codeplex.com/discussions/267900
I have an extremely strange Problem, while trying to develop for android on eclipse
my program always returned non-sense statements, so I tried debugging it.
And Now I understand what the problem is....
...the code acts literally crazy - it's absolutely illogical
this is my code:
ArrayList<String[]> formatedVerses = readAndSplitDatabaseFile(database, books);
if (formatedVerses.size() < 1) { // check if readAndSplitDatabaseFile worked
createDatabase(database, false); // if not. the database wasnt initialized
formatedVerses = readAndSplitDatabaseFile(database, books); // try again
}
return formatedVerses;
basically I create this ArrayList
But when I debug, it doesnt just go trough the code from top to bottom, it makes weird illogical jumps
the debugger arrives at the line:
ArrayList<String[]> formatedVerses = readAndSplitDatabaseFile(database, books);
then jumps to the if-statement (so far so good)
if (formatedVerses.size() < 1) {
but "formatedVerses.size() < 1" is false, so it should jump over the if-block
but instead the debugger not only jumps INTO the if-block, but it actually jumps into THE SECOND LINE of the block:
formatedVerses = readAndSplitDatabaseFile(database, books);
which makes no sense whatsoever.
I feel like somebody is playing jokes on me.
I just cant wrap my mind around this.....
I've also tried restructuring the code...
but it only gets weirder.
I've also tried other implementations. for example like this:
if (formatedVerses.size() < 1) {
return array1;
} else{
doSomethingElse();
return array2;
}
in that case, it jumps into the true-statement of the if-block
return array1;
and then, when I click on next-step, it actually JUMPS from that line to the
return array2 line inside of the else-block, while completely leaving out the doSomethingElse()-line
anybody got any ideas?
because I'm going crazy right now...
Usually when I see behavior like this, it is because I am not running the code I think I am running. I have not done Android development, so I can't speak specifically to that, but do you have "build automatically" under the project menu checked? I have found that to reduce the number of times I see this behavior tremendously.
Have you tried cleaning the code and doing a complete rebuild? Are you running this out of Eclipse or on a remote device? If on a remote device, have you published the code to the device?
As I said, I haven't done any Android development, so some of these questions may seem obvious from an Andriod developing standpoint.
Hope those ideas help.
To me, it actually sounds like your braces are misaligned in some way. It appears to be ignoring the braces around the if statement, treating it like this.
if (formatedVerses.size() < 1) // check if readAndSplitDatabaseFile worked
createDatabase(database, false); // if not. the database wasnt initialized
formatedVerses = readAndSplitDatabaseFile(database, books); // try again
Doesn't really explain your second example though.
EDIT: Or maybe your second block is also parsing oddly.. doesn't explain why the code continues after a return statement though.
if (formatedVerses.size() < 1)
return array1;
else
doSomethingElse();
return array2;
just to elaborate on what aperkins said, which is all correct, the Eclipse debugger uses line number information from when your code was compiled into a .class file, and uses your source .java file to display what line of code is being run. So say you write this :
if (readAndSplitDatabaseFile(database, books).size() < 1) {
createDatabase(database, false); // if not. the database wasnt initialized
formatedVerses = readAndSplitDatabaseFile(database, books); // try again
}
return formatedVerses;
and you build and run, and then you add a line of code and a blank line:
ArrayList<String[]> formatedVerses = readAndSplitDatabaseFile(database, books);
if (formatedVerses.size() < 1) { // check if readAndSplitDatabaseFile worked
createDatabase(database, false); // if not. the database wasnt initialized
formatedVerses = readAndSplitDatabaseFile(database, books); // try again
}
return formatedVerses;
now when you are debugging, you are stepping through the first example, but looking at the second. The solution as aperkins mentioned is just to build and run again, or to undo your changes until they match up with what you had when you last compiled.
Okay, I figured it out.
Strangely it was something completely different.
I made some mistakes on the complete other side of my program. It had nothing to do with this code-segment (the problems weren't even in the same class.)
once that was fixed, it started to act normal again.
I don't understand it and at this point, I don't want to understand it.
Thanks for the help, everybody.