There are a couple of questions already on SO assessing the possibility of executing self generated code. The generic answer is that it's possible, it's being done in JIT compilers and with dynamic library loading.
The application is in optimisation of sparse convolutions where the sparse structure should be embedded in the code, since skipping multiplication by zeros conditionally is slower than multiplying by zeros. Neither it's feasible in terms of performance to encode the structure in data:
do { // actually: don't do this
auto offset = *encoded_offset++;
auto coeff = *encoded_coefficient++;
accum += data[offset] * coeff;
} while (end_of_data); // e.g. offset < 0, or offset == previous offset
Vs.
...
ldr q5, [x1], 16 ; load data
fmla v0.4s, v5.4s, v8.s[0]
fmla v1.4s, v5.4s, v8.s[1]
fmla v2.4s, v5.4s, v8.s[2]
// fmla v3.4s, v5.4s, v8.s[3] ; omitted, when |weight| < threshold
fmla v4.4s, v5.4s, v8.s[3] ; we reuse the v8.s[3] with a weight that matters
ldr q5, [x1], 16
// fmla v0.4s, v5.4s, v9.s[0] ; omitted, when |weight| < threshold
// fmla v1.4s, v5.4s, v9.s[0] ; omitted
fmla v2.4s, v5.4s, v9.s[0]
fmla v3.4s, v5.4s, v9.s[1]
fmla v4.4s, v5.4s, v9.s[2]
; + several kilobytes of instructions
It's possible to generate the code by templates, but it would be far more efficient (and marginally more secure reverse engineering in mind) if the code was generated on the fly.
Now the question is, how to exactly call the generated function in some of the most important mobile ecosystems: Ios, android and possibly webassembly (using off course WASM (SIMD) bytecode).
What exact system calls need to be issued to be able to execute the block of memory filled with the code -- legally?
The only problem you will stumble upon is that "normal" memory is usually protected against execution. You just need to set on that memory the execute permission.
After that you can set any sort of instructions you want. See for example the top fizzbuzz bandwidth winner, who uses a simple JIT machine.
https://codegolf.stackexchange.com/a/236630/108147
But the basic code is this:
#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
uint8_t code[] = { 0x89, 0xf8, // mov eax, edi
0x0f, 0xaf, 0xc6, // imul eax, esi
0xc3 }; // ret
int main() {
using multifn = int( int a, int b);
size_t pagesize = getpagesize();
size_t codesize = ((sizeof(code)-1)/pagesize+1)*pagesize;
uint64_t codeaddr = uint64_t(code);
codeaddr -= codeaddr % pagesize;
mprotect((void*)codeaddr, codesize, PROT_READ | PROT_WRITE |PROT_EXEC);
multifn* m = reinterpret_cast<multifn*>(code);
std::cout << "Result:" << m(2,3) << std::endl;
return 0;
}
I just ran it in my Linux box as a regular user and the result is:
Program stdout
Result:6
I assume that as Android is basically Linux, the result will be the same. As per IOS I have to speculate here.
Also Godbolt: https://godbolt.org/z/hsMKWsjM9
If you are really picky about not messing up with regular memory, you can create a separate page for your generated code
#include <string>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
void* createExecPage( size_t size ) {
size_t pagesize = getpagesize();
size = ((size-1)/pagesize+1)*pagesize;
std::cout << "Pagesize:" << pagesize << " size:" << size << std::endl;
void* temp = nullptr;
int res = posix_memalign(&temp, pagesize, size );
if ( res!=0 ) {
perror("posix_memalign");
}
res = mprotect(temp, size, PROT_READ | PROT_WRITE |PROT_EXEC);
if ( res!=0 ) {
perror( "mprotect" );
}
return temp;
}
uint8_t code[] = { 0x89, 0xf8, // mov eax, edi
0x0f, 0xaf, 0xc6, // imul eax, esi
0xc3 }; // ret
int main()
{
using multifn = int( int a, int b);
void* xpage = createExecPage(sizeof(code));
memcpy( xpage, code, sizeof(code));
multifn* m = reinterpret_cast<multifn*>(xpage);
std::cout << "Result:" << m(2,3) << std::endl;
return 0;
}
https://godbolt.org/z/ebW76o1KP
Related
I have found a bug in the Android NDK compiler (r16b). Code snippet is shown below:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int frameWidth = 208;
int main(int argc, char* argv[])
{
int32_t count = (argc > 1) ? atoi(argv[1]) : -1;
int width = frameWidth;
int rows = count / (width * sizeof(int16_t));
if (rows >= 3) {
printf("rows=%u\n", rows);
} else {
printf("count=%d rows=%d\n", count, rows);
}
}
The problem is the gcc/llvm compiler is treating the divide as an unsigned divide. You can see this by compiling the code to a cmdline executable and running with no arguments or a negative number and/or generating the assembly code and looking at the arm source:
#DEBUG_VALUE: main:count <- %R4
.loc 1 11 22 is_stmt 0 # ./main.c:11:22
mov r0, r4
.Ltmp8:
bl __aeabi_uidiv
mov r2, r0
.Ltmp9:
#DEBUG_VALUE: main:rows <- %R2
.loc 1 12 9 is_stmt 1 # ./main.c:12:9
cmp r2, #3
blt .LBB0_5
Where do I report this bug so it can be fixed? I can imagine there are other places in our code where a signed divide is expected.
You can report issues in the official NDK GitHub repository:
https://github.com/android-ndk/ndk/issues
I'am using a develop board of samsung s5p6818 soc. After choosing "user mode spi""SLSI SPI port0" on menuconfig, and adding these code in plat-s5p6818/drone/device.c,
/*------------------------------------------------------------------------------
* SSP/SPI
*/
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <mach/slsi-spi.h>
static struct s3c64xx_spi_csinfo spi0_csi[] = {
[0] = {
.line = CFG_SPI0_CS,
.set_level = gpio_set_value,
.fb_delay = 0x2,
},
};
static struct spi_board_info spi_plat_board[] __initdata = {
[0] = {
.modalias = "spidev", /* fixup */
.max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0, /* Note> set bus num, must be smaller than ARRAY_SIZE(spi_plat_device) */
.chip_select = 0, /* Note> set chip select num, must be smaller than spi cs_num */
.controller_data = &spi0_csi[0],//spi0_info,
.mode = SPI_MODE_3 | SPI_CPOL | SPI_CPHA,
},
};
#endif
spi_register_board_info(spi_plat_board,ARRAY_SIZE(spi_plat_board));
/*--------------------------------------------------------------------------*/
I can find "spidev0.0" in /dev when Android system is operating on my board. However, this device dosen't work when I use a testing program calling the function read/write, and cause my system to reboot (function "open","ioctl" can work properly). Here is my testing code
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#define SPI_IOC_MAGIC 'k'
#define SPI_CPHA 0x01
#define SPI_CPOL 0x02
#define SPI_MODE_0 (0|0)
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
typedef unsigned char __u8;
typedef unsigned int __u32;
/* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */
#define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8)
#define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8)
/* Read / Write SPI bit justification */
#define SPI_IOC_RD_LSB_FIRST _IOR(SPI_IOC_MAGIC, 2, __u8)
#define SPI_IOC_WR_LSB_FIRST _IOW(SPI_IOC_MAGIC, 2, __u8)
/* Read / Write SPI device word length (1..N) */
#define SPI_IOC_RD_BITS_PER_WORD _IOR(SPI_IOC_MAGIC, 3, __u8)
#define SPI_IOC_WR_BITS_PER_WORD _IOW(SPI_IOC_MAGIC, 3, __u8)
/* Read / Write SPI device default max speed hz */
#define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32)
#define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32)
static int fd = 0;
int main(void)
{
// int fd = -1;
int buf[1000];
int i = 0;
fd = open("/dev/spidev0.0", O_RDWR);
if(fd < 0){
printf("open /dev/spidev0.0 error!!!\n");
}
printf("-------------===============------------fd=%d\n",fd);
spi_init();
for (i=0;i<1000;i++)
{
buf[i]=0x33333333;
}
for(i=0;i<20;i++)
{ write(fd,buf,1000*4);
}
return 0;
}
void spi_init(void){
int ret = 0;
int speed = 2*1000*1000;
int delay;
unsigned char bits = 32;
unsigned char mode = SPI_MODE_1;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if(ret == -1){
printf("can't set spi mode\n");
}else{
printf("set spi mode %d\n",ret);
}
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if(ret == -1){
printf("can't get spi mode\n");
}else{
printf("get spi mode %d\n",ret);
}
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if(ret == -1){
printf("can't set bits per word\n");
}else{
printf("set bits per word %d\n",ret);
}
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if(ret == -1){
printf("can't get bits per word\n");
}else{
printf(" get bits per word %d\n",ret);
}
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if(ret == -1){
printf("can't set max speed hz\n");
}else{
printf("set max speed hz %d\n",ret);
}
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if(ret == -1){
printf("can't get max speed hz\n");
}else{
printf("get max speed hz %d\n",ret);
}
}
Here is my debug loglog
I think this is because I didn't config gpio correctly, but I don't know how and where to config gpio pins. I hope someone can teach me how to make this correct.
you can set gpio function in plat-s5p6818/drone/include/cfg_gpio.h for examples check how i2c bus interface is defined for your arch.
I've a rooted phone with Android 4.2.2. I'd like to use minui API used (source here) in bootloader code to draw stuff on the screen. minui is much simpler than native OpenGL and I don't need any complex functionality exposed by OpenGL.
The problem is that I can't write stuff directly to fb0 device. FBIOPUT_VSCREENINFO fails for unknown reason.
How can I draw directly to fb0 on Android, or how can I use minui outside the bootloader mode?
device node:/dev/graphics/fb0
you can build in Android tree or use arm-linux-gcc.
arm-linux-gcc -D__ANDROID__ fb-test.c -static
likes a normal embeded linux, there is a sample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
struct fb_fix_screeninfo FixedInfo;
struct fb_var_screeninfo OrigVarInfo;
static int FrameBufferFD = -1;
void *FrameBuffer = (void *) -1;
#ifndef __ANDROID__
#define FRAMEBUFFER "/dev/fb0"
#else
#define FRAMEBUFFER "/dev/graphics/fb0"
#endif //__ANDROID__
void openFBDEV(void)
{
/* open the framebuffer device */
FrameBufferFD = open(FRAMEBUFFER, O_RDWR);
if (FrameBufferFD < 0)
{
fprintf(stderr, "Error opening %s\n", FRAMEBUFFER);
exit(1);
}
/* Get the fixed screen info */
if (ioctl(FrameBufferFD, FBIOGET_FSCREENINFO, &FixedInfo))
{
fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed\n");
exit(1);
}
/* get the variable screen info */
if (ioctl(FrameBufferFD, FBIOGET_VSCREENINFO, &OrigVarInfo))
{
fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed\n");
exit(1);
}
if (FixedInfo.visual != FB_VISUAL_TRUECOLOR
&& FixedInfo.visual != FB_VISUAL_DIRECTCOLOR)
{
fprintf(stderr,
"non-TRUE/DIRECT-COLOR visuals (0x%x) not supported by this demo.\n",
FixedInfo.visual);
exit(1);
}
/*
* fbdev says the frame buffer is at offset zero, and the mmio region
* is immediately after.
*/
/* mmap the framebuffer into our address space */
FrameBuffer = (void *) mmap(0, /* start */
FixedInfo.smem_len, /* bytes */
PROT_READ | PROT_WRITE, /* prot */
MAP_SHARED, /* flags */
FrameBufferFD, /* fd */
0 /* offset */);
if (FrameBuffer == (void *) -1)
{
fprintf(stderr, "error: unable to mmap framebuffer\n");
exit(1);
}
}
void closeFBDEV(void)
{
munmap(FrameBuffer, FixedInfo.smem_len);
close(FrameBufferFD);
}
int main()
{
openFBDEV();
fprintf(stderr, "openFBDEV finish\n");
memset(FrameBuffer, 128, FixedInfo.smem_len);
sleep(5);
closeFBDEV();
fprintf(stderr, "closeFBDEV finish\n");
return 0;
}
Source code,test it works in Qualcomm platform MSM89xx:
panel_test.c
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "yellow_face.zif"
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
struct fb_cmap cmapinfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
int b,g,r;
// Open the file for reading and writing
fbfd = open("/dev/graphics/fb0", O_RDWR,0); // 打开Frame Buffer设备
if (fbfd < 0) {
printf("Error: cannot open framebuffer device.%x\n",fbfd);
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) { // 获取设备固有信息
printf("Error reading fixed information.\n");
exit(2);
}
printf("\ntype:0x%x\n", finfo.type ); // FrameBuffer 类型,如0为象素
printf("visual:%d\n", finfo.visual ); // 视觉类型:如真彩2,伪彩3
printf("line_length:%d\n", finfo.line_length ); // 每行长度
printf("\nsmem_start:0x%lx,smem_len:%u\n", finfo.smem_start, finfo.smem_len ); // 映象RAM的参数
printf("mmio_start:0x%lx ,mmio_len:%u\n", finfo.mmio_start, finfo.mmio_len );
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) { // 获取设备可变信息
printf("Error reading variable information.\n");
exit(3);
}
printf("%dx%d, %dbpp,xres_virtual=%d,yres_virtual=%dvinfo.xoffset=%d,vinfo.yoffset=%d\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel,vinfo.xres_virtual,vinfo.yres_virtual,vinfo.xoffset,vinfo.yoffset);
screensize = finfo.line_length * vinfo.yres_virtual;
// Map the device to memory 通过mmap系统调用将framebuffer内存映射到用户空间,并返回映射后的起始地址
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fbfd, 0);
if ((int)fbp == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
/***************exampel 1**********************/
b = 10;
g = 100;
r = 100;
for ( y = 0; y < 340; y++ )
for ( x = 0; x < 420; x++ ) {
location = (x+100) * (vinfo.bits_per_pixel/8) +
(y+100) * finfo.line_length;
if ( vinfo.bits_per_pixel == 32 ) { //
*(fbp + location) = b; // Some blue
*(fbp + location + 1) = g; // A little green
*(fbp + location + 2) = r; // A lot of red
*(fbp + location + 3) = 0; // No transparency
}
}
/*****************exampel 1********************/
/*****************exampel 2********************/
unsigned char *pTemp = (unsigned char *)fbp;
int i, j;
//起始坐标(x,y),终点坐标(right,bottom)
x = 400;
y = 400;
int right = 700;//vinfo.xres;
int bottom = 1000;//vinfo.yres;
for(i=y; i< bottom; i++)
{
for(j=x; j<right; j++)
{
unsigned short data = yellow_face_data[(((i-y) % 128) * 128) + ((j-x) %128)];
pTemp[i*finfo.line_length + (j*4) + 2] = (unsigned char)((data & 0xF800) >> 11 << 3);
pTemp[i*finfo.line_length + (j*4) + 1] = (unsigned char)((data & 0x7E0) >> 5 << 2);
pTemp[i*finfo.line_length + (j*4) + 0] = (unsigned char)((data & 0x1F) << 3);
}
}
/*****************exampel 2********************/
//note:vinfo.xoffset =0 vinfo.yoffset =0 否则FBIOPAN_DISPLAY不成功
if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) {
printf("Error FBIOPAN_DISPLAY information.\n");
exit(5);
}
sleep(10);
munmap(fbp,finfo.smem_len);//finfo.smem_len == screensize == finfo.line_length * vinfo.yres_virtual
close(fbfd);
return 0;
}
Android.mk
# Copyright 2006-2014 The Android Open Source Project
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= panel_test.c
LOCAL_SHARED_LIBRARIES := $(common_libs) libqdutils libdl liblog libbase libcutils
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
LOCAL_MODULE := panel_test
LOCAL_CFLAGS := -Werror
include $(BUILD_EXECUTABLE)
include $(call first-makefiles-under,$(LOCAL_PATH))
yellow_face.zif
yellow_face.zif
I'm very newbie in Android world and I have to write an streaming video quality checker application on Android. I have to use the native StageFright media framework to play videos. As far as I understand there is an native API of render statistics, but I need advice how I can get it. Thank you.
There is an ADB command to print playback framerate.
Procedure
Open console on windows (or linux) on the host. Make sure that required drivers have been installed for USB connectivity with the device (android phone or board)
Run the following commands
$> adb kill-server
$> adb shell setprop debug.video.showfps 1
Run the video playback. If the video is being run using Android Media player stack, then you will see prints reporting frame rate achieved.
You're welcome to use this as well, call it at the beginning and end of each frame rendered. It's a slightly altered version of some sample code from the NDK:
stats.c:
#include <sys/time.h>
#include <string.h>
#include <android/log.h>
#include <stdio.h>
#include "stats.h"
#define LOG_TAG "[STATS]"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define STATS_DUMP(...) __android_
double now_ms()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec*1000. + tv.tv_usec/1000.;
}
void stats_init(Stats* s)
{
s->lastTime = now_ms();
s->firstTime = 0.;
s->firstFrame = 0;
s->numFrames = 0;
s->dump = malloc(128);
memset(s->dump,0,128);
}
void stats_startFrame(Stats* s)
{
s->frameTime = now_ms();
}
void stats_endFrame(Stats* s)
{
double now = now_ms();
double renderTime = now - s->frameTime;
double frameTime = now - s->lastTime;
int nn;
if (now - s->firstTime >= MAX_PERIOD_MS) {
if (s->numFrames > 0) {
double renderTime = now - s->frameTime;
double frameTime = now - s->lastTime;
int nn;
double minRender, maxRender, avgRender;
double minFrame, maxFrame, avgFrame;
int count;
nn = s->firstFrame;
minRender = maxRender = avgRender = s->frames[nn].renderTime;
minFrame = maxFrame = avgFrame = s->frames[nn].frameTime;
for (count = s->numFrames; count > 0; count-- ) {
nn += 1;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS;
double render = s->frames[nn].renderTime;
if (render < minRender) minRender = render;
if (render > maxRender) maxRender = render;
double frame = s->frames[nn].frameTime;
if (frame < minFrame) minFrame = frame;
if (frame > maxFrame) maxFrame = frame;
avgRender += render;
avgFrame += frame;
}
avgRender /= s->numFrames;
avgFrame /= s->numFrames;
sprintf(s->dump,"Frames per second - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]Rendering time ms - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]", 1000./avgFrame, 1000./maxFrame, 1000./minFrame, avgRender, minRender, maxRender);
//LOGI("Frames per second - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]Rendering time ms - [AVG:%.1f] [MIN:%.1f] [MAX:%.1f]", 1000./avgFrame, 1000./maxFrame, 1000./minFrame, avgRender, minRender, maxRender);
}
s->numFrames = 0;
s->firstFrame = 0;
s->firstTime = now;
}
nn = s->firstFrame + s->numFrames;
if (nn >= MAX_FRAME_STATS)
nn -= MAX_FRAME_STATS;
s->frames[nn].renderTime = renderTime;
s->frames[nn].frameTime = frameTime;
if (s->numFrames < MAX_FRAME_STATS) {
s->numFrames += 1;
} else {
s->firstFrame += 1;
if (s->firstFrame >= MAX_FRAME_STATS)
s->firstFrame -= MAX_FRAME_STATS;
}
s->lastTime = now;
}
stats.h:
#include <jni.h>
#define MAX_FRAME_STATS 120
#define MAX_PERIOD_MS 5000
typedef struct{
double renderTime;
double frameTime;
} FrameStats;
typedef struct{
double firstTime;
double lastTime;
double frameTime;
int firstFrame;
int numFrames;
FrameStats frames[ MAX_FRAME_STATS ];
char* dump;
} Stats;
extern double now_ms();
extern void stats_init(Stats *);
extern int stats_dump(Stats *);
extern void stats_startFrame(Stats *);
extern void stats_endFrame(Stats *);
I wrote a simple loop to aid in billboarding that will check if a pixel is white. if so, it will set it to 100% transparency. i wrote it in native code because the java equivalent of this loop took 19 seconds to run for a 256x256 bitmap, too slow.
when compiling:
#include "org_me_renderscene_Billboard.h"
#include <stdio.h>
#include <stdlib.h>
JNIEXPORT jintArray JNICALL Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite
(JNIEnv *envptr, jclass jClass, jintArray pixels, jint length)
{
int *mPixels = (*int)malloc(length * 4);
static int currentcolor;
static int writecolor;
static int red, green, blue;
for(int x = 0; x < length; x++)
{
currentcolor = pixels[x];
red = currentcolor << 16;
green = currentcolor << 8;
blue = currentcolor;
if((red == 0) && (green == 0) && (blue == 0))
{
mPixels[x] = 0x00000000;
}
else
{
mPixels[x] = currentcolor;
}
}
return mPixels;
}
the auto-generated stub for which is:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_me_renderscene_Billboard */
#ifndef _Included_org_me_renderscene_Billboard
#define _Included_org_me_renderscene_Billboard
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_me_renderscene_Billboard
* Method: NativeSetAlphaWhereWhite
* Signature: ([II)[I
*/
JNIEXPORT jintArray JNICALL Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite
(JNIEnv *, jclass, jintArray, jint);
#ifdef __cplusplus
}
#endif
#endif
i get these errors:
thomas#THOMASDESKLINUX:~/Documents/LinuxProgramming/EclipseWorkspace/RenderScene$ /home/thomas/Documents/LinuxProgramming/AndroidSDKs/android-ndk-r4b/ndk-build
Compile thumb : Billboardlib <= /home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c: In function 'Java_org_me_renderscene_Billboard_NativeSetAlphaWhereWhite':
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:9: error: expected expression before 'int'
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:9: error: expected ',' or ';' before 'malloc'
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:15: error: 'for' loop initial declarations are only allowed in C99 mode
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:15: note: use option -std=c99 or -std=gnu99 to compile your code
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:17: warning: dereferencing 'void *' pointer
/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/jni/org_me_renderscene_Billboard.c:17: error: void value not ignored as it ought to be
make: *** [/home/thomas/Documents/LinuxProgramming/EclipseWorkspace/RenderScene/obj/local/armeabi/objs/Billboardlib/org_me_renderscene_Billboard.o] Error 1
why is this happening? my C code should be fine, and these errors dont make much sense.
Try (int*) instead of (*int)
what flags are you using in you Android.mk ?
did you set LOCAL_CFLAGS := -std=c99
also
you need to change to this
int *mPixels = (int*)malloc(length * 4);
int *mPixels = (*int)malloc(length * 4);
should be
int *mPixels = (int*)malloc(length * 4);
or even better
int *mPixels = (int*)malloc(length * sizeof(int));
and also note that this will not properly separate red, green, and blue:
red = currentcolor << 16;
green = currentcolor << 8;
blue = currentcolor;
Given that you're just checking for zero, and you don't really care about the individual RGB values, you can probably just get away with:
if ( (currentcolor & 0x00FFFFFF) == 0)
This will zero out the Alpha from the pixel, leaving behind just the RGB portion. If that whole thing is zero, each color must be zero, so there's no need to check each color individually.
Final thought:
I haven't done much with Android specifically, but isn't 0x000000 black and 0xFFFFFF white? So you're actually matching on black instead of white here.