I'm doing some cross platform development, and I ran across another weird problem..
namespace Math
{
#include <math.h>
}
This is what I am trying to do. It works fine on iOS, but on Android everything inside math.h is not a member of Math when I try to compile it. After some trial an error I found out that the ndk doesn't put the stuff in math.h in the namespace Math, as the functions do exist without the Math:: prefix. The big problem is that some functions in math.h clash with my own convenience functions. How can I fix this?
You really shouldn't try to put any system headers into a different namespace. The solution, as painful as it may be at this point in development, is to put all of your code into its own namespace.
What about <cmath>? it puts everything in std:: (in C++11).
Don't put your convenience functions in the global namespace.
Don't try to wrap math.h in a namespace.
There, all’OK now.
Cheers & hth.,
Probably something else includes math.h earlier in the preprocessor "pipeline". C includes check whether the sane include has been included earlier. In this case, the check #ifndef MATH_H resulted in excluding the whole file. Try placing your include with the namespace at the beginning of your .c files.
Related
I've successfully written a go mobile library and used it from an Android Java app.
I've also successfully called a c function from JNI. This one has the JNIEnv pointer.
I'd like to pass the context/JNIEnv from Java to Go.
Here's where it seems to get complicated:
Go Mobile does not seem to use JNIEnv at all.
LoadJNI.java does have a context object and claims to pass it to the Go side. But there it isn't visible.
I've been able to include jni.h using the "C" directive
I can transfer the JNIEnv from JNI/C or store it there as a global variable but that's an ugly kludge.
https://github.com/golang/go/issues/16876 talks about a proposal to do reverse binding but it's unclear what the status is.
https://godoc.org/golang.org/x/mobile/cmd/gobind also talks about it but the following code snippet
import "Java/java/lang/System"
t := System.CurrentTimeMillis()
returns
cannot find package "Java/java/lang/System" in any of:
/usr/local/go/src/Java/java/lang/System (from $GOROOT)
/Users/----/go/src/Java/java/lang/System (from $GOPATH)
In C I solved it with a compiler directive: #cgo CFLAGS: -I...
But I'm not sure how to do it for Java
In short, I'm now stuck and would appreciate help. Ideally, I'd just like to pass the object as a parameter, if possible. However, I'd settle for any reverse binding to call Java from Go.
I hate to answer my own question, but I'd hate someone to go through this as well too. I'll update this answer as I go along.
Basic Setup
Edit build.gradle and add GOPATH and GO to gobind (additions in bold):
gobind {
pkg = ".../reverse/reverse"
GOPATH = "/Users/johndoe/go"
GO = "/usr/local/go/bin"
}
How to develop
Start from the reverse example. Get it to compile and run.
Make one modification and recompile.
Missing gobind
It turns out the installation process neglected to build gobind. Run go install golang.org/x/mobile/cmd/gobind
I'm Stuck
Trying to modify the reverse project to do anything other than what it's already doing is failing. Even stuff like passing an object and calling toString will fail.
More to come...
I am trying to include the ads by making them part of my xml layout, I noticed on this quickstart guide: https://developer.amazon.com/sdk/mobileads/quick-start.html it says that you should have the namespace as "xmlns:Amazon="http://schemas.android.com/apk/res/"". However when I tried this intelij says that the namepace is never used and the ad never shows up in the layout. I looked in the sample provided in the sdk and for their namespace they didn't use their package name but instead: "xmlns:Amazon="http://schemas.android.com/apk/lib/com.amazon.device.ads"". So I am wondering what the correct namepace is that I should be using
I noticed on this quickstart guide it says that you should have the namespace as "xmlns:Amazon="http://schemas.android.com/apk/res/""
I looked in the sample provided in the sdk and for their namespace they didn't use their package name but instead: "xmlns:Amazon="http://schemas.android.com/apk/lib/com.amazon.device.ads""
That first statement is not correct. In the quickstart guide it actually says that the namespace should be:
xmlns:Amazon="http://schemas.android.com/apk/res/<type your package name>"
Note the last part. That's important, because that's exactly the difference you're basing this question on.
As with any custom view on Android, if you want to use one or more attributes that aren't covered by the Android namespace, you have to declare their location first. Normally, that means you copy the line above and append the package name of your project. The Amazon prefix can be pretty much anything you like, but it makes sense to give the namespace a name that is related to its definition.
In this case, declaring the Amazon namespace, enables the usage of the Amazon:adSize attribute in the layout file. Without that declaration, your IDE will not know where to look for the adSize attribute.
That being said, if you don't use any custom attributes, then there is no point in declaring the namespace, as you won't be using it. That's basically what IntelliJ is telling you. In other words: if you're not using Amazon:adSize in your layout, you can safely remove the Amazon namespace declaration.
I am trying to use a hash_map, defined in the Android NDK, but I get a "deprecation warning":
ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/ext/../backward/backward_warning.h:33:2:
error: #warning This file includes at least one deprecated or antiquated header which may
be removed without further notice at a future date. Please use a non-deprecated interface
with equivalent functionality instead. For a listing of replacement headers and
interfaces, consult the file backward_warning.h. To disable this warning use -Wno-
deprecated. [-Werror=cpp]
And since "unordered_map" is present in gnu-libstdc++/4.6/include/ and also in gnu-libstdc++/4.6/include/tr1/, I believe that there is a way to use it.
The point is that I cannot find it. Which of the following is the right one (if any):
#include <tr1/unordered_map.h>
#include <unordered_map>
And then, how to use it? __gnu_cxx::unordered_map is not recognized... and I don't know how to find this information.
In case you don't want/need C++11 support, you can use the one from the STLPort using:
// Here we are referencing the stlport one:
#include <unordered_map>
...
std::tr1::unordered_map<int, int> test;
That's because STLPort defines unordered_map inside tr1 namespace, but the STLPort header is not inside any /tr1/ folder.
I eventually found a way by adding C++11 support in my Android project. Pretty easy when we know it, but I took some time to figure it out. Neither STLPort nor Boost were needed. Once C++11 was integrated, I could use "unordered_map" as follows:
#include <unordered_map>
...
std::unordered_map<int, int> test;
I created a new question to explain how to enable C++11 support in Android here.
I have a library that I want to customize its work (I mean replacing the main of the library by my outside program so I can for example reorder the calls of the library's functions) and for that I had to change some static variable to extern variables so the library and my program can handle them both.
My program works fine when on run on my Linux desktop machine, however when I tried to port that to Android using NDK, I couldn't compile it because of the extern keyword .
So, I was wondering if there's a way concerning the Android.mk or alternative to the use of extern keyword, to make the things work.
You're getting an "undefined reference" because extern is not a variable definition, only a declaration. That means you must have an non-extern declation somewhere else in your code, otherwise the compiler doesn't allocate a symbol for your variable.
As for alternatives, no, an extern variable is the only way to have a global variable accross multiple object files in C.
If you only need a global variable in the same object file, you can use static so the symbol is not exported to other objects.
I'm just messing around with a Ndk tutorial I found. The native code uses one "package", while the activity is in another. When this mismatch occurs, I can't call the native function without getting an unsatisfied link exception. I know the "why's" I just don't know the resolution.
Here is the sample .c code that I've placed in my jni folder:
#include <string.h>
#include <jni.h>
jstring Java_com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from native code!");
}
Notice that this .c code's package translates to com.mindtherobot.samples.ndkfoo.NdkFooActivity.
If I create a new activity that matches that Package/Class, I can call the invokeNativeFunction just fine. However, what if I can't match it? What if instead I need to run it from com.mydomain.activity?
I figured I could maybe change things around, such that my native declaration looked like this:
package com.mydomain;
public class Activity {
private native String com_mindtherobot_samples_ndkfoo_NdkFooActivity_invokeNativeFunction();
}
But that's a no-go. Just to be clear, I know how to make this work if I change my package to match what is compiled in the .c code; however, I need to be able to call a method from a different package... is this possible?
You need to make a basic class with the sole functionality of talking to C, not an activity. Then activities can instantiate this class, or possibly even statically call it, whenever they need to talk to C.
Your question is pretty scrambled, but the package declaration in the Java source code has to agree with what is encoded into the native method name, i.e. it must agree with what is generated by javah. If you change the package in the Java code, you must regenerate the .h file, and adjust the .c file to suit. There is no other way to fudge around this.