2016-05-02 3 views
2

В настоящее время я работаю над I2C между малиной Pi 3 и PsoC 4. Я использую библиотеку I2C-dev для обработки сообщений I2C. Таким образом, шина I2C запущена и работает, и функция чтения и записи реализована правильно. Я хочу, однако, чтобы функция указателя на функцию чтения и записи, следовательно, к функциям используют одни и те же тип аргументов (по крайней мере это выглядит) я следующий основной код называется II2C-dev: изменить параметры записи и чтения

2Ctest-tools.cpp:

#include <unistd.h>    //Needed for I2C port 
#include <fcntl.h>    //Needed for I2C port 
#include <sys/ioctl.h>   //Needed for I2C port 
#include <linux/i2c-dev.h>  //Needed for I2C port 
#include <stdio.h> 
#include "i2c.h" 
#include "functions.h" 


int main() { 


     int addr = 0x49; 
     int cmd = 2; //Write 
     int length = 5; 
     int file_i2c = 0; 
     I2C myI2C; 



     unsigned char buffer[5]; 

     buffer[0] = 0x01; 
     buffer[1] = 0x02; 
     buffer[2] = 0x20; 
     buffer[3] = 0x00; 
     buffer[4] = 0x17; 

     i2c_init(&myI2C, cmd, addr, &file_i2c); 
     i2c_exe(&myI2C, file_i2c, buffer, length); 

    return 0; 
} 

Как показано в коде, im использует объект struct myI2C, который передается в двух функциях i2c_init, i2c_exe. Исходный код для functions.cpp заключается в следующем:

#include <unistd.h>    //Needed for I2C port 
#include <fcntl.h>    //Needed for I2C port 
#include <sys/ioctl.h>   //Needed for I2C port 
#include <linux/i2c-dev.h>  //Needed for I2C port 
#include <stdio.h> 
#include "i2c.h" 
#include "functions.h" 

int i2c_init(I2C *cthis, int cmd, int addr, int *ptrFile_i2c) { 
    char *filename = (char*)"/dev/i2c-1"; 
    if ((*ptrFile_i2c = open(filename, O_RDWR)) < 0) 
    { 
     //ERROR HANDLING: you can check errno to see what went wrong 
     printf("Failed to open the i2c bus"); 
     return 0; 
    } 

    if (ioctl(*ptrFile_i2c, I2C_SLAVE, addr) < 0) 
    { 
     printf("Failed to acquire bus access and/or talk to slave.\n"); 
     //ERROR HANDLING; you can check errno to see what went wrong 
     return 0; 
    } 

    switch(cmd) { 
     case 1: 
      //cthis->WR = write; 
      break; 
     case 2: 
      cthis->WR = read; 
      break; 
    } 
    return 0; 
} 

int i2c_exe(I2C *cthis, int file_i2c, unsigned char *buffer, size_t length) { 

    cthis->WR(file_i2c, buffer, length); 
    return 0; 
} 

Так важно здесь отметить, что в функции i2c_init им переключения на varialbe ЦМД, который диктует, будет ли указатель функции указывает на записи или функции чтения. Теперь отказ часть приходит в указателе функции объявлена ​​в собственном .h файл под названием i2c.h и выглядит следующим образом:.

struct I2C { 
    ssize_t (*WR)(int, const void *, size_t); 
}; 

Как вы можете видеть, что указатель функции должен указывать на функцию с параметрами (интермедиат, сопзЬ пустота *, size_t) это работает как шарм, когда функция точки на функции записи, но когда он указывает на функцию чтения им получать и ошибка, ошибка говорит:

functions.cpp: In function ‘int i2c_init(I2C*, int, int, int*)’: functions.cpp:30:14: error: invalid conversion from ‘ssize_t ()(int, void, size_t) {aka int ()(int, void, unsigned int)}’ to ‘ssize_t ()(int, const void, size_t) {aka int ()(int, const void, unsigned int)}’ [-fpermissive] cthis->WR = read;

Я изучал и пришел к выводу, что это потому, что функция чтения и записи каким-то образом не принимает те же аргументы, что и странно, потому что im передает в них одни и те же аргументы (int i2 s_file, внутр буфер, внутр длина), так что если я изменить указатель на функцию

ssize_t (*WR)(int, void *, size_t); 

функция работает с чтения, но не с записью .. Так что мой вопрос: могу ли я каким-то образом изменить запись или функцию чтения взять тот же аргумент, изменив библиотеку i2c-dev или есть что-нибудь еще, что я мог бы сделать, чтобы решить эту проблему?

здесь ссылка на библиотеку i2c-DEV, который я полностью отказавшись понять http://textuploader.com/5yioi

Благодаря передовой

ответ

1

можно заливать функции явно к нужному типу:

typedef ssize_t (*I2CCMD)(int, void *, size_t); 

cthis->WR = (I2CCMD)write; 

cthis->WR = (I2CCMD)read; 

Это должно устранить ошибку.

+0

Да, это исключает ошибку и вызывает неопределенное поведение из-за несовместимых типов указателей функций. Скорее всего, это будет работать на практике. – Lundin

+0

@ EmilMøllerRinggaard Важно, чтобы вы поняли, что этот код основан на плохо заданном поведении. Вы должны задокументировать это в комментариях. В противном случае ваша программа может быть не переносимой. – Lundin

+0

@lundin okay ... –

0

Функция read не может принимать указатель на const, поскольку в отличие от функции write она должна изменить этот параметр.

Таким образом, вы не можете переключать функциональность с помощью указателя функции, поскольку указатели на функции имеют разные типы.

Лучшие обходные, кажется, либо перемещение параметра «ЦМД» функции i2c_exe, или же создать приватную переменную, содержащую cmd (внутри struct I2C было бы идеально). А затем в i2c_exe либо вызовите чтение, либо запись.

Хуже решение изменить-структуру для объединения, как:

union I2C { 
    ssize_t (*WR)(int, const void *, size_t); 
    ssize_t (*read)(int, void*, size_t); 
}; 

Тогда в случае чтения, используйте элемент для чтения, чтобы назначить структуры. Но учтите, что это своего рода «грязный хак», это слабоопределенное поведение в теории. На практике это, скорее всего, будет работать в любой системе. (Очень маловероятно, что константная корректность когда-либо повлияет на соглашение о вызове.)

Смежные вопросы