Как передать char * из C в CPP? - PullRequest
       22

Как передать char * из C в CPP?

3 голосов
/ 07 декабря 2010

Немного предыстории: у меня есть библиотека кода C, которая является частью большой системы (все C).Для этой конкретной части библиотеки C должен быть создан графический интерфейс, который позволяет пользователям поиграть с опциями.Для графического интерфейса я выбрал QT, так как желательна межплатформенная поддержка.Я использую Eclipse и MinGW в качестве IDE и компилятора (но я думаю, что вопрос больше в языке, чем в конкретном компиляторе?).

С QT я создал виджет, который содержит указатель на структуру, реализованную в Cон содержит указатели на несколько функций, которые выполняют логику библиотеки C.

//QTWidget.cpp
extern "C" {
#include "c-src/CLogic.h"
//extern char* textHelper;
}

QTWidget::QTWidget(QWidget *parent)
{
    //rtw is a struct that contains a function pointer to a member of QTWidget
    this->rtw.displayText = &QTWidget::displayText;
    this->clogic = CLogic_getInstance(&rtw);
}

//Public SLOT, connected to a button's clicked SIGNAL
void QTWidget::buttonClicked()
{
    this->clogic->buttonClicked();
}

void QTWidget::displayText(char *text, int position)
{
    //I've tried creating a QString from the char*, but this does not work at all.
    //ui.textItem->setText(textHelper);
    ui.textItem->setText(text);
}

Когда пользователь нажимает кнопку в графическом интерфейсе, вызывается метод QTWidget :: buttonClicked (), который сообщает библиотеке Cсделать что-то.Обратите внимание, что структура CLogic имеет ссылку на QTWidget в форме структуры RefToWidget, которая содержит указатель на функцию.

//CLogic.c
static CLogic instance;

void CLogic_buttonClicked()
{
    //I've tried several variants here, such as making a global 
    //char* textHelper = "Hello World"; 
    //that is referenced by using the "extern" keyword in the CPP file above.
    instance.rtw->displayText("Hello World", 1);
}
CLogic* CLogic_getInstance(RefToWidget *rtw)
{
    instance.rtw = rtw;
    instance.buttonClicked = &CLogic_buttonClicked();
}

При отладке этой программы я обнаружил, что все вызовы функций выполняются, как предполагалось(когда я нажимаю кнопку, вызывается buttonClicked () слота QT, вызывается CLogic_buttonClicked (), который вызывает QTWidget :: displayText (), как и планировалось, но в этом последнем вызове параметры недопустимы. Текстовые символы char *на 0x1 и утверждает, что указывает на память вне границ, а позиция int выглядит как какое-то случайное число (неинициализированное).

Как передать эти данные из C в CPP?

РЕДАКТИРОВАТЬ@Luccas Matteis:

#ifdef __cplusplus
#include "QTWidget.h"

extern "C" {
#endif

struct RefToWidget{
#ifdef __cplusplus
    void (QTWidget::*displayLine)(char* text, int lineNumber);
#else
    void (*displayLine)(char* text, int lineNumber);
#endif
};

typedef struct RefToWidget RefToWidget;
#ifdef __cplusplus
}
#endif

Как уже было сказано выше, вызовы функций ведут себя, как и ожидалось, но данные не передаются «правильно» (хотя, когда я на это смотрю, код кажется немного ...странно ...;))

Ответы [ 3 ]

4 голосов
/ 07 декабря 2010

Ваша проблема не в передаче char * из C в C ++, а в вызов функции C ++ из C. Я предполагаю, что CLogic.c скомпилирован как библиотека C?Если нет, можете ли вы переименовать его в CLogic.cpp или использовать переключатель компилятора, чтобы заставить его быть скомпилированным как C ++, даже если он имеет расширение файла C?

Если вам нужен графический интерфейс C ++ в библиотеке C /Система, вам нужно использовать правильную логику Model-View-Controller.Здесь код C ++ - это View и Controller, а код C - это Model (насколько я могу судить из вашего описания).Вам нужно сделать так, чтобы вы устанавливали и получали данные из модели, но модель никогда не вызывает View или Controller, как вы пытаетесь это сделать.

Подумайте о том, что вы ДЕЙСТВИТЕЛЬНО пытаетесь сделать.Если вы просто хотите отображать статическую строку при нажатии кнопки, зачем переходить к вызову CLogic.c?Если вы хотите отобразить строку, которая зависит от состояния экземпляра CLogic, вместо этого сделайте что-то вроде:

void QTWidget::buttonClicked()
{
    char *display_text = this->clogic->get_button_click_text();
    ui.textItem->setText(display_text);
}
1 голос
/ 07 декабря 2010

Думаю, проблема в том, что структура содержит указатель на функцию-член. Функция-член, вероятно, ожидает, что первым параметром будет «this» - объект, на который она ссылается. Итак, на самом деле то, что вы видите в тексте отладки, является вторым параметром.

«Решением», вероятно, было бы сделать что-то вроде «instance.rtw-> displayText (instance.rtw,« Hello World », 1)», но понятия не имею, переносимо ли оно и т. Д.

Редактировать: Говорить об этом явно: «решение», изложенное выше, просто пытается проверить, является ли это проблемой. Как говорится в комментариях, это ужасный хак, который может не сработать даже на одном и том же компиляторе.

0 голосов
/ 07 декабря 2010

Я не думаю, что вам следует вызывать метод C ++ из C. Обычно вам нужно пройти статический метод, который разыменовывает аргумент указателя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...