0

I'm trying to use canutils in an android ndk-project. the package canutils usually compiles to executable files, but i didnt find a way yet to inlude these executables in an ndk-project. so what im doing at the moment is just loading the shared libraries like this:

static{
System.loadLibrary("cansend");
}
public native void cansend();

that for I've changes the android-mk to build shared libraries instead.

still my c-code looks like this cansend.c as an example :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <linux/can.h>
#include <linux/can/raw.h>

#include "lib.h"

int main(int argc, char **argv)
{
int s; /* can raw socket */ 
int required_mtu;
int mtu;
int enable_canfd = 1;
struct sockaddr_can addr;
struct canfd_frame frame;
struct ifreq ifr;

/* check command line options */
if (argc != 3) {
    fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
    return 1;
}

/* parse CAN frame */
required_mtu = parse_canframe(argv[2], &frame);
if (!required_mtu){
    fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n");
    fprintf(stderr, "    <can_id>#{R|data}          for CAN 2.0 frames\n");
    fprintf(stderr, "    <can_id>##<flags>{data}    for CAN FD frames\n\n");
    fprintf(stderr, "<can_id> can have 3 (SFF) or 8 (EFF) hex chars\n");
    fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally");
    fprintf(stderr, " seperated by '.')\n");
    fprintf(stderr, "<flags> a single ASCII Hex value (0 .. F) which defines");
    fprintf(stderr, " canfd_frame.flags\n\n");
    fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / ");
    fprintf(stderr, "123##1 / 213##311\n     1F334455#1122334455667788 / 123#R ");
    fprintf(stderr, "for remote transmission request.\n\n");
    return 1;
}

/* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    perror("socket");
    return 1;
}

addr.can_family = AF_CAN;

strcpy(ifr.ifr_name, argv[1]);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
    perror("SIOCGIFINDEX");
    return 1;
}
addr.can_ifindex = ifr.ifr_ifindex;

if (required_mtu > CAN_MTU) {

    /* check if the frame fits into the CAN netdevice */
    if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
        perror("SIOCGIFMTU");
        return 1;
    }
    mtu = ifr.ifr_mtu;

    if (mtu != CANFD_MTU) {
        printf("CAN interface ist not CAN FD capable - sorry.\n");
        return 1;
    }

    /* interface is ok - try to switch the socket into CAN FD mode */
    if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
               &enable_canfd, sizeof(enable_canfd))){
        printf("error when enabling CAN FD support\n");
        return 1;
    }

    /* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
    frame.len = can_dlc2len(can_len2dlc(frame.len));
}

/* disable default receive filter on this RAW socket */
/* This is obsolete as we do not read from the socket at all, but for */
/* this reason we can remove the receive list in the Kernel to save a */
/* little (really a very little!) CPU usage.                          */
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror("bind");
    return 1;
}

/* send frame */
if (write(s, &frame, required_mtu) != required_mtu) {
    perror("write");
    return 1;
}

close(s);

return 0;
}

I want to be able to use this cansend method in my android-ndk-project. Do I need to adjust the c-code and make a shared library out of the code or do i need to use the executable and call and include it in my project in a certain way to be able to use it?

4
  • Turning it into a shared library might be the easier way, but both should be possible. Commented Jun 11, 2013 at 11:02
  • but if i turn it into a shared library, do i need to change the whole c-code and can i use this c-code as a shared libary and call cansend somehow? Commented Jun 11, 2013 at 11:10
  • Sure, you just have to rename main, I think. Commented Jun 11, 2013 at 12:52
  • i'm not sure if i understand you. can i just rename my main89 for example to cansend() and it should work as a shared library? Commented Jun 12, 2013 at 8:26

1 Answer 1

1

Rename your main function or put another wrapper around it. If you want your native function to be named as cansend(), your wrapper function should be something like this:

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT 
void
Java_com_aaa_bbb_ccc_cansend( JNIEnv* env, jobject thiz);

#ifdef __cplusplus
}
#endif

Here, com_aaa_bbb_ccc comes from your package name of your java code which contains public native void cansend();.

For example, if your package name is com.example.test, your function name will be:

Java_com_example_test_cansend();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.