标签归档:Eclipse

在Unity Android 程序中使用动态库及注意事项

很多C/C++代码以动态库的方式供第三方调用,在Unity中,这类文件(dll for windows, *.so file for Android/Linux, *.dylib for MAC OSX)叫插件。

在Unity开发的Android程序中使用动态库插件是非常方便的,曾经因为被误导而放弃使用unity,转而研究Android通过原生Java的JNI方式包装*.so文件,虽然还行,但是JNI晦涩丑陋的API实在看着不舒服。相对而言,C#也是可以直接包装*.so文件并在Android系统中直接调用的,而且Unity制作Android app跟Unity制作其他平台的app是无缝的,只是在发布时选择要发布的平台就行了,真正做到了平台无关,极大的方便了开发。

我还没仔细研究如何在Android Studio中开发NDK,这里只介绍如何用Eclipse开发NDK。

在Eclipse中开发NDK的几个必须的安装项:NDK编译环境、Android SDK直接从官网单独下载单独安装;CDT、ADT插件可以直接从Eclipse的help的插件管理中安装。

然后就可以创建项目了:

1、打开Eclipse,通过File->New Project,弹出对话框,填入项目名称:

01

2、点Next,出现Config Project窗口:

02

由于只用于编译NDK,所以把前两项的钩钩去掉,第三个勾上,标记为so项目;目录也自定义一下,因为通常情况下我只会为编译so文件配置项目,真正的代码会单独放在更顶层的目录,方便跨平台的其他编译项目使用。结果如下:

03

4、按Finish结束创建过程,目录结构如下:

04

5、添加Native代码支持。也就是JNI相关的东西:在左侧项目根目录上右键->Android Tools->Add Native Support…

05

在随后弹出的对话框中输入要生成的so文件的名字:

06

这时候会发现多了一个目录:

07

6、编译配置

在jni目录中加入Application.mk文件和Android.mk文件

Application.mk:

APP_ABI      := all
#APP_ABI       := armeabi-v7a
#APP_ABI       += armeabi

#APP_OPTIM        := release
APP_PLATFORM     := android-8
#APP_BUILD_SCRIPT := Android.mk

# GNU STL implements most C++11 features. Use either gnustl_static or gnustl_shared
# Without this your C++ code will not be able to access headers like <thread>, <mutex>
#APP_STL := stlport_static
#APP_CPPFLAGS := -std=c++11 -frtti -fexceptions 
APP_STL       := gnustl_static
APP_CPPFLAGS  := -std=gnu++11 -pthread -frtti -fexceptions -DNDEBUG #-NDEBUG -mfpu=neon -fomit-frame-pointer -DULM_BLOCKED -msse3 -mfpmath=sse

Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := PNLib
LOCAL_SRC_FILES := PNLib.cpp

include $(BUILD_SHARED_LIBRARY)

本来Android.mk文件很简单,把所有头文件、cpp文件加入,直接编译就行。但是对于我的项目这远远不够,因为我的代码要跨平台,有各个平台的编译项目单独出去,同时使用一份src文件,所以代码被放到了顶层目录中的src目录下,我需要遍历这个目录并把它加入NDK编译系统中来,所以下面从网上找了一段遍历头文件和cpp文件的脚本来用了:

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE   := PNLib

# 锟斤拷锟斤拷锟皆硷拷锟斤拷源锟侥硷拷目录锟斤拷源锟侥硷拷锟斤拷缀锟斤拷
MY_FILES_PATH  :=  $(LOCAL_PATH)/../../src

#$(warning $(MY_FILES_PATH))

MY_FILES_SUFFIX := %.cpp %.c

# 递归遍历目录下的所有的文件
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# 获取相应的源文件
MY_ALL_FILES := $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*.*) ) 
MY_ALL_FILES := $(MY_ALL_FILES:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)
MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(MY_ALL_FILES)) 
MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)

# 去除字串的重复单词
define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

# 递归遍历获取所有目录
MY_ALL_DIRS := $(dir $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*/) ) )
MY_ALL_DIRS := $(call uniq,$(MY_ALL_DIRS))

# 赋值给NDK编译系统
LOCAL_SRC_FILES  := $(MY_SRC_LIST)
LOCAL_C_INCLUDES := $(MY_ALL_DIRS)

# Add additional include directories
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../Eigen-3.2.2   
#必须从Android.mk配置文件中拿掉对Eigen的直接包含,放到程序代码中用相对路径包含:
# #include "../../Eigen-3.2.2/Eigen"
# using namespace Eigen;

#$(warning $(LOCAL_SRC_FILES))
#$(warning $(LOCAL_C_INCLUDES))

# use log system in NDK
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

7、最后一步是为此项目配置一个NDK编译工具:

A、项目->右键->Properties,弹出项目属性对话框:

08

B、选中Builders,点击New按钮,弹出框中选中“Program”,点击OK:

09

C、出现新Builder配置对话框,随便起个名字“New_Builder_for_NDK”;

在Main标签页中,“Location”项,通过“Browse File System…“找到NDK的build文件,windows系统为ndk-build.cmd,Mac或其他类Linux系统为ndk-build;

工作目录”Working Directory“指定当前项目下的jni目录就行了。

10

D、切到Refresh页,勾选”Refresh resources upon completion“

11

E、切到”Build Options“页,勾选”Specify working set of relevant resources“,点击后面按钮”Specify Resources…“,指本项目下的jni目录。

12

最后的编译条如下:

13

点击左边锤子图标即可对项目进行编译。剩下的工作就是一步步修正跨平台代码,最后生成PNLib.so文件。

 

以上步骤有几个地方需要特别注意:

1、使用gun++11

NKD支持c++11,GCC已经支持大部分c++11特性,所以可以直接使用gun++11。实际上,如果用c++11,Android版程序可能报错:DLLNotFundException,编译出来的动态库在Android系统中无法加载,所以Application.mk文件中必须如下配置:

APP_STL       := gnustl_static
APP_CPPFLAGS  := -std=gnu++11 -pthread -frtti -fexceptions -DNDEBUG

2、x64版ndk目前还有bug

你的系统即便是x64的,也别下载x64版本的ndk,否则会报找不到make.exe的问题(make.exe不是内部命令XXXXXXXXX)

 

3、不识别vector、list等模板类的问题

Add

APP_STL := stlport_static

to their Application.mk file.

其实Android插件应该用APP_STL := gnustl_static

 

4、使用第三方库Eigen导致array等冲突的问题

原因是在NDK的Android.mk文件中把Eigen的路径也加入到里面了。

正确的做法是,不在Android.mk文件加入Eigen,而是在程序代码中直接包含Eigen头文件。

 

Eclipse+CDT+Cygwin,让我情何以堪啊……

为了编写跨平台程序,一是采用了Eclipse+CDT+Cygwin开发,中间真是莫名其妙的问题层出不穷,每次解决了问题,不知道什么时候又回冒出来,而有些问题,第一次出现后记录下来的解决办法,第二次却无法依据同样的方法解决,真是让人欲哭无泪啊……

1、multiple target patterns问题

记得最先碰到这个问题,可以在项目的Properties的C/C++Builder—>Tool Chain Editor—>Current toolchain选择Cygwin,Current Builder由Gnu Maker Builder改为CDT Internal Builder解决。据说是因为Gun Maker的3.8.0版本有bug,改成3.8.1可以解决问题,当然可以选用CDT Internal Builder,也能解决这个问题。but,有时候,你用CDT Internal Builder,一样产生multiple target patterns问题,汗。。。

另一种说法是windows下的盘符后的冒号(如”D:\“)会被Maker解释成对象分隔符,从而导致Maker错误的认为后面是个编译对象,从而导致multiple target patterns问题,解决办法是在主菜单—>Window—>Preferences—>C/C++—>Debug—>Source Look Path中点击Add按钮,选择Path Mapping,添加盘符映射(如’C:\’映射成’\cygdrive\c\’、’D:\’映射成’\cygdrive\d\’)来解决。但貌似也不见得有效,汗。。。

2、同一个项目中的.cpp文件竟然找不到自己的.h文件

这个问题郁闷了我好几天,发现是因为一个项目引用另一个动态库项目时,如果通过Properties—>C/C++ General—>Path and Symbal—>References中勾选要引用的dll项目进行自动引用,用CDT Internal Builder则会出现同一个项目中的.cpp文件找不到自己的.h文件的问题,只好把CDT Internal Builder改成Gun Maker,然后再在Properties—>C/C++ Builder—>Settings的Includes和Libraries中手动加入对动态库的引用,即可解决问题。汗。。。

Shared libraries with Eclipse CDT and cygwin on Windows

Can you help me use shared libraries with Eclipse CDT, managed make and cygwin?“, I was asked yesterday. Read on for a list of common pitfalls and detailed instructions.

The instructions are based on the latest CDT release (Galileo) and cygwin (make 3.81, gcc 3.4.4). They are applicable to CDT’s managed make projects (that means CDT generates a makefile to build project).

The Pitfalls

It turns out that using a shared library on Windows is not as straight forward as you think. There are several pitfalls waiting for the unaware to fall into:

1. Recent versions of cygwin’s make insist on cygwin-style paths instead of windows paths (/cygdrive/c/foo instead of c:\foo). CDT is not picky about this and will generate an incorrect makefile, if you use workspace relative paths:

make all
example.d:1: *** multiple target patterns.  Stop.

The solution is to use absolute cygwin paths, such as: /cygdrive/c/workspace/mymath

2. The compiler and linker will not find the header files / library unless you set the appropriate parameters. The compiler needs an include path (-I). The linker needs the library name (-l) and library search path (-L). These settings are scattered in two places in the project properties. Their location is not obvious for a first-time user (details below).

3. When launching, Windows will not find the shared library (.dll) and greet you with the error pictured below. Unix users might try to set the LD_LIBRARY_PATH, which has no effect on Windows. The solution is to append the directory containing the .dll to the PATH (MSDN Article). Restart Eclipse for the changed PATH to take effect.

The remainder of the post walks you through the process of creating and using a simple shared library with cygwin and CDT.

Creating a Shared Library with CDT

Follow these instructions to create a shared library project with CDT.

1. File > New > Project > C Project > Next. Project name: mymath. Ensure “use default location” is checked. Note the location: c:\workspace\mymath — we’ll need it later. Project type: Shared Library; Empty Project. Hit Finish.

2. Create a header file (mymath.h) and the corresponding implementation (mymath.c). The example below provides a trivial function that multiplies two integers:

3. Afterwards save and hit Ctrl+B (or Project > Build All) to build the library. If cygwin is on your path, you should see a “Release” folder in your project containing the file “mymath.dll”.

4. For windows to find the shared library, you need to add the directory containing the .dll to your path. On Vista this can be done via: Control Panel > User Accounts > User Accounts > Change my environment variables.

5. Exit and restart Eclipse after changing the PATH. Otherwise the changes will not be picked up.

Using a Shared Library with CDT

Follow these instructions to use a shared library in a “managed make” CDT project.

1. File > New > Project > C Project > Next. Project name: example. Project type: Executable; Empty Project. Hit Finish.

2. In that project create a file named example.c with the following content:

3. Save and hit Ctrl+B to build the project. The second line will have an error: “mymath.h: No such file or directory”. We now have to adjust the compiler and linker settings so that the mymath.h / mymath.dll files are found during the build.

4. Select the “example” folder in the Project Explorer. Select “Project > Properties” from the menu. A dialog comes up. In the tree on the left open: “C/C++ General > Paths and Symbols”. In the “Languages” list, pick “GNU C”. Then hit “Add”. Enter the cygwin-style path to the “mymath” project: /cygdrive/c/workspace/mymath

Caution: When entering the path, don’t use the “Workspace” or “File system” buttons because the resulting path will not be compatible with cygwin’s make.

5. In the same dialog select: C/C++ Build > Settings in the tree on the left. In the “Tool Settings” tab find: “Cygwin C Linker > Libraries”. Hit the “+” icon in the “Libraries” section and add the name of the library: mymath

Caution: if your shared library starts with lib, omit the ‘lib’ prefix (i.e. libfoo becomes foo)

Hit the “+” icon in the “Library search path” section and add the path to the folder containing the shared library:/cygdrive/c/workspace/mymath/Debug

Hit OK.

6. You will be asked to rebuild the project. Answer “Yes”, but for some reason this will not rebuild your project. Hit Ctrl+B to rebuild. The error will go away.

Note: ignore the “unresolved inclusion” warning. It seems that CDT has trouble resolving cygwin-style paths. The generated make-file however will work as expected.

7. Select “example” in the Project Explorer. Right-click > Run As > Local C/C++ Application. At this point you see the result of the multiplication on the console. That means that the shared library was found and used successfully:

Kind regards,
Elias.

 

本文转自:http://eclipsesource.com/blogs/2010/03/03/shared-libraries-with-eclipse-cdt-and-cygwin-on-windows/

解决 undefined reference to `_uncompress’ `_compress’问题

在eclipse+CDT+mysql环境下编译项目,出现如下错误:

Building target: dbdeal.dll
Invoking: Cygwin C++ Linker
g++ -L”C:\cygwin\code\trunk\Utility\Debug” -L”C:\cygwin\code\trunk\log\Debug” -L”C:\cygwin\usr\local\lib\mysql” -shared -o”dbdeal.dll” ./LoadSticTable.o ./ParseCommand.o ./SQLQuery.o ./TableModels/TabBase.o ./TableModels/tabAnalysisData.o ./TableModels/tabCmdBuffer.o ./TableModels/tabDevice.o ./TableModels/tabFirmware.o ./TableModels/tabRawData.o ./TableModels/tabUser.o ./TableModels/tabWarningRecord.o -lUtility -llog -lmysqlclient
C:\cygwin\usr\local\lib\mysql/libmysqlclient.a(my_compress.o):my_compress.c:(.text+0x5f): undefined reference to `_uncompress’
C:\cygwin\usr\local\lib\mysql/libmysqlclient.a(my_compress.o):my_compress.c:(.text+0x1aa): undefined reference to `_compress’
collect2: ld returned 1 exit status
make: *** [dbdeal.dll] Error 1

?
网上找了很多关于‘undefined reference to `_uncompress’’的问题,但都很草草的说给gcc添加‘-lz’参数可以解决问题日,但是问为啥,都说不出个所以然来。
很多都是命令行编译,而我用的是eclipse,makefile动态生成,所以去修改makefile是不明智的,只能从配置入手。
在项目上右键—>属性,出现属性对话框,到‘Cygwin C++ Linker’项下的‘Miscellaneous’里的‘Linker flags’输入参数‘ -lz’:

编译看看,发现-lz参数被直接串在了lib库查询路径的后面,而不是mysqlclient的后面:

g++ -L”C:\cygwin\code\trunk\Utility\Debug” -L”C:\cygwin\code\trunk\log\Debug” -L”C:\cygwin\usr\local\lib\mysql” -lz -shared -o”dbdeal.dll”

所以‘-lz’参数对mysqlclient不起作用。
其实在‘Expert settings’中有个‘Command line pattern’的设置:

${COMMAND} ${FLAGS} ${OUTPUT_FLAG}${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}

其中的‘${FLAGS}’变量就是上面设置‘-lz’参数的‘Linker flags’,解决办法出来了:把 ${FLAGS} 挪到 ${INPUTS} 之后,问题解决:

Ubuntu下安装Eclipse CDT

Ubuntu 在安装时,如同大部分 Linux 发行版一样,都会同时安装 GNU 版本的 Java。这个 Java 的实用程度太低,尤其对于开发人员来说,是没有太多用处的。在 Ubuntu 下,安装 SUN Java 是一件很容易的事情。第一步:

sudo apt-get install sun-java6-jre
sudo apt-get install sun-java6-jdk

安装完毕之后,选择默认 java:

sudo update-alternatives --config java

然后配置环境变量:

sudo vim /etc/environment

在其中添加如下两行:

CLASSPATH=/usr/lib/jvm/java-6-sun/lib
JAVA_HOME=/usr/lib/jvm/java-6-sun

保存退出。 之后安装配置 Eclipse。安装很简单:

sudo apt-get install eclipse

虽然已经这时新安装的 java 已经成为系统默认的 jvm,但是 Eclipse 并不会用 update-alternative 设置的
jvm 来启动自身,而使用的是以前的 GNU Java。GNU Java 是 1.4.2 的实现,而且在性能上远不如 SUN 的实现。为了让
Eclipse 利用 SUN Java 启动,我们还需要继续配置。首先把 SUN Java 完完全全的设置为系统的默认 JDK:

sudo update-java-alternatives -s java-6-sun

然后编辑 JVM 配置文件:

sudo vim /etc/jvm

把文件中的

/usr/lib/jvm/java-6-sun

这一行移动到配置块的顶部。由于 Eclipse 会忽略 Ubuntu 的通用 Java 设置(貌似一个 bug),我们需要继续编辑 Eclipse 的
java_home 文件:

sudo vim /etc/eclipse/java_home

如同上面一样,把

/usr/lib/jvm/java-6-sun

这一行移动到文件的顶部。所有的安装配置完成之后,Ubuntu 的 Java 开发平台就基本完备了。


安装CDT:


http://www.eclipse.org/cdt/downloads.php
下载CDT

tar zxvf org.eclipse.cdt-3.1.2-linux.x86.tar.gz

解压后将features和plugins文件夹下的所有文件拷贝到/usr/lib/eclipse下对应的目录下即可

原文:http://blog.csdn.net/firefoxboy/archive/2008/11/26/3380225.aspx