gpt4 book ai didi

android - 链接器命令在 Android Studio 中失败并退出代码 1?

转载 作者:太空狗 更新时间:2023-10-29 13:53:27 26 4
gpt4 key购买 nike

我在 android studio 中使用位图操作 native 库,但编译非常好,但运行时抛出链接器命令失败,退出代码 1(使用 -v 查看调用)

我被放置在 c 代码之后。

#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>

#define LOG_TAG "DEBUG"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

extern "C"
{
//store
JNIEXPORT jobject JNICALL Java_photoeditor_com_myapplication_MainActivity_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
//get
JNIEXPORT jobject JNICALL Java_photoeditor_com_myapplication_MainActivity_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
//free
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
//rotate 90 degrees CCW
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle);
//rotate 90 degrees CW
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniRotateBitmapCw90(JNIEnv * env, jobject obj, jobject handle);
//crop
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom);
//scale using nearest neighbor
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniScaleNNBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t newWidth, uint32_t newHeight);
}

class JniBitmap
{
public:
uint32_t* _storedBitmapPixels;
AndroidBitmapInfo _bitmapInfo;
JniBitmap()
{
_storedBitmapPixels = NULL;
}
};

/**crops the bitmap within to be smaller. note that no validations are done*/ //
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniCropBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
uint32_t oldWidth = jniBitmap->_bitmapInfo.width;
uint32_t newWidth = right - left, newHeight = bottom - top;
uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
uint32_t* whereToGet = previousData + left + top * oldWidth;
uint32_t* whereToPut = newBitmapPixels;
for (int y = top; y < bottom; ++y)
{
memcpy(whereToPut, whereToGet, sizeof(uint32_t) * newWidth);
whereToGet += oldWidth;
whereToPut += newWidth;
}
//done copying , so replace old data with new one
delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
jniBitmap->_bitmapInfo.width = newWidth;
jniBitmap->_bitmapInfo.height = newHeight;
}

/**rotates the inner bitmap data by 90 degress counter clock wise*/ //
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniRotateBitmapCcw90(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo;
uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int whereToGet = 0;
// XY. ... ... ..X
// ...>Y..>...>..Y
// ... X.. .YX ...
for (int x = 0; x < bitmapInfo.width; ++x)
for (int y = bitmapInfo.height - 1; y >= 0; --y)
{
//take from each row (up to bottom), from left to right
uint32_t pixel = previousData[whereToGet++];
newBitmapPixels[bitmapInfo.width * y + x] = pixel;
}
delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
uint32_t temp = bitmapInfo.width;
bitmapInfo.width = bitmapInfo.height;
bitmapInfo.height = temp;
}

JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniRotateBitmapCw90(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
AndroidBitmapInfo bitmapInfo = jniBitmap->_bitmapInfo;
uint32_t* newBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int whereToGet = 0;
// XY. ..X ... ...
// ...>..Y>...>Y..
// ... ... .YX X..
for (int x = bitmapInfo.width - 1; x >= 0; --x)
for (int y = 0; y < bitmapInfo.height; ++y)
{
//take from each row (up to bottom), from left to right
uint32_t pixel = previousData[whereToGet++];
newBitmapPixels[bitmapInfo.width * y + x] = pixel;
}
delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
uint32_t temp = bitmapInfo.width;
bitmapInfo.width = bitmapInfo.height;
bitmapInfo.height = temp;
}

/**free bitmap*/ //
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
delete[] jniBitmap->_storedBitmapPixels;
jniBitmap->_storedBitmapPixels = NULL;
delete jniBitmap;
}

/**restore java bitmap (from JNI data)*/ //
JNIEXPORT jobject JNICALL Java_photoeditor_com_myapplication_MainActivity_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
{
LOGD("no bitmap data was stored. returning null...");
return NULL;
}
//
//creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
//
//LOGD("creating new bitmap...");
jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jstring configName = env->NewStringUTF("ARGB_8888");
jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.width, jniBitmap->_bitmapInfo.height, bitmapConfig);
//
// putting the pixels into the new bitmap:
//
int ret;
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, newBitmap);
//LOGD("returning the new bitmap");
return newBitmap;
}

/**store java bitmap as JNI data*/ //
JNIEXPORT jobject JNICALL Java_photoeditor_com_myapplication_MainActivity_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
{
AndroidBitmapInfo bitmapInfo;
uint32_t* storedBitmapPixels = NULL;
//LOGD("reading bitmap info...");
int ret;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
{
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return NULL;
}
//LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
{
LOGE("Bitmap format is not RGBA_8888!");
return NULL;
}
//
//read pixels of bitmap into native memory :
//
//LOGD("reading bitmap pixels...");
void* bitmapPixels;
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
{
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return NULL;
}
uint32_t* src = (uint32_t*) bitmapPixels;
storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
int pixelsCount = bitmapInfo.height * bitmapInfo.width;
memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
AndroidBitmap_unlockPixels(env, bitmap);
JniBitmap *jniBitmap = new JniBitmap();
jniBitmap->_bitmapInfo = bitmapInfo;
jniBitmap->_storedBitmapPixels = storedBitmapPixels;
return env->NewDirectByteBuffer(jniBitmap, 0);
}

/**scales the image using the fastest, simplest algorithm called "nearest neighbor" */ //
JNIEXPORT void JNICALL Java_photoeditor_com_myapplication_MainActivity_jniScaleNNBitmap(JNIEnv * env, jobject obj, jobject handle, uint32_t newWidth, uint32_t newHeight)
{
JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
if (jniBitmap->_storedBitmapPixels == NULL)
return;
uint32_t oldWidth = jniBitmap->_bitmapInfo.width;
uint32_t oldHeight = jniBitmap->_bitmapInfo.height;
uint32_t* previousData = jniBitmap->_storedBitmapPixels;
uint32_t* newBitmapPixels = new uint32_t[newWidth * newHeight];
int x2, y2;
int whereToPut = 0;
for (int y = 0; y < newHeight; ++y)
{
for (int x = 0; x < newWidth; ++x)
{
x2 = x * oldWidth / newWidth;
if (x2 < 0)
x2 = 0;
else if (x2 >= oldWidth)
x2 = oldWidth - 1;
y2 = y * oldHeight / newHeight;
if (y2 < 0)
y2 = 0;
else if (y2 >= oldHeight)
y2 = oldHeight - 1;
newBitmapPixels[whereToPut++] = previousData[(y2 * oldWidth) + x2];
//same as : newBitmapPixels[(y * newWidth) + x] = previousData[(y2 * oldWidth) + x2];
}
}

delete[] previousData;
jniBitmap->_storedBitmapPixels = newBitmapPixels;
jniBitmap->_bitmapInfo.width = newWidth;
jniBitmap->_bitmapInfo.height = newHeight;
}

我正在使用 stacktrace 那个时间显示在我输入的异常之后

enter image description here

Cmakelists.txt 内部配置

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

add_library( # Sets the name of the library.
JniBitmapOperations

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
# Associated headers in the same location as their source
# file are automatically included.
src/main/cpp/JniBitmapOperations.cpp )

find_library( # Sets the name of the path variable.
log-lib
JniBitmapOperations
# Specifies the name of the NDK library that
# you want CMake to locate.
log
)
target_link_libraries( # Specifies the target library.

JniBitmapOperations

# Links the target library to the log library
# included in the NDK.
)

Android.mk文件内容

LOCAL_PATH := $(call my-dir)

#bitmap operations module
include $(CLEAR_VARS)

LOCAL_MODULE := JniBitmapOperations
LOCAL_SRC_FILES := JniBitmapOperations.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g

#if you need to add more module, do the same as the one we started with (the one with the CLEAR_VARS)

添加调用 java jniBitmapHolder.java 文件,不再有进程仅编译和构建我的项目以抛出此异常。

import android.graphics.Bitmap;
import android.util.Log;

import java.nio.ByteBuffer;

public class JniBitmapHolder
{
ByteBuffer _handler =null;
static
{
System.loadLibrary("JniBitmapOperations");
}

private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);

private native void jniFreeBitmapData(ByteBuffer handler);

private native void jniRotateBitmapCcw90(ByteBuffer handler);

private native void jniRotateBitmapCw90(ByteBuffer handler);

private native void jniCropBitmap(ByteBuffer handler,final int left,final int top,final int right,final int bottom);

private native void jniScaleNNBitmap(ByteBuffer handler,final int newWidth,final int newHeight);

public JniBitmapHolder()
{}

public JniBitmapHolder(final Bitmap bitmap)
{
storeBitmap(bitmap);
}

public void storeBitmap(final Bitmap bitmap)
{
if(_handler!=null)
freeBitmap();
_handler=jniStoreBitmapData(bitmap);
}

public void rotateBitmapCcw90()
{
if(_handler==null)
return;
jniRotateBitmapCcw90(_handler);
}

public void rotateBitmapCw90()
{
if(_handler==null)
return;
jniRotateBitmapCw90(_handler);
}

public void cropBitmap(final int left,final int top,final int right,final int bottom)
{
if(_handler==null)
return;
jniCropBitmap(_handler,left,top,right,bottom);
}

public Bitmap getBitmap()
{
if(_handler==null)
return null;
return jniGetBitmapFromStoredBitmapData(_handler);
}

public Bitmap getBitmapAndFree()
{
final Bitmap bitmap=getBitmap();
freeBitmap();
return bitmap;
}

public void scaleBitmap(final int newWidth,final int newHeight)
{
if(_handler==null)
return;
jniScaleNNBitmap(_handler,newWidth,newHeight);
}

public void freeBitmap()
{
if(_handler==null)
return;
jniFreeBitmapData(_handler);
_handler=null;
}

@Override
protected void finalize() throws Throwable
{
super.finalize();
if(_handler==null)
return;
Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
freeBitmap();
}
}

构建 gradle 文件配置。

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
useLibrary 'org.apache.http.legacy'
defaultConfig {
applicationId "com.itflash.whatsappstickers"
minSdkVersion 18
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true

ndk {
moduleName "JniBitmapOperations"
ldLibs "log", "jnigraphics"
//abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86'
}

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cmake {
cppFlags "-frtti -fexceptions"
arguments '-DANDROID_PLATFORM=android-19', '-DANDROID_TOOLCHAIN=clang'
}
}
}
}
packagingOptions {
exclude 'META-INF/NOTICE' // will not include NOTICE file
exclude 'META-INF/LICENSE' // will not include LICENSE file
exclude 'META-INF/DEPENDENCIES'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
dexOptions {
incremental true
javaMaxHeapSize "1536m"
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.google.android.gms:play-services:10.2.0'
compile 'com.android.support:appcompat-v7:25.2.0'
testCompile 'junit:junit:4.12'
}

最佳答案

链接器无法找到您使用的函数,即您必须手动指定库。在我看来,好像那应该是 libjnigraphics

您是否在 Android.mk 中指定了 LOCAL_LDFLAGS += -ljnigraphics,如 this answer 所示?

关于android - 链接器命令在 Android Studio 中失败并退出代码 1?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42779951/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com