Проблемы с пониманием синтаксиса C ++ std :: function - PullRequest
0 голосов
/ 02 октября 2019

У меня проблемы с отправкой сообщений из функции регистрации DLL в функцию регистрации клиента. Я в порядке, используя указатель на функцию, как это:

DLL:

class InnerLogger
{
public:
    static std::function<void(const std::string& message, int level)> loggerCallback;
    static std::stringstream logMsg;
    static int logSend(LogLevel logLevel);
};

void setLoggingFunction(const std::function<void(const std::string& message, int level)>& logFunction)
{
    InnerLogger::loggerCallback = logFunction;
}

Клиент:


void outerLogger(const std::string& message, int level)
{
  // display/save messages
}

main()
{
    std::function<void(const std::string& message, int level)> logFunctionPtr = outerLogger;
    setLoggingFunction(logFunctionPtr);
}

Я могу использовать InnerLogger :: logSend, и outerLogger выбирает егоup.

Но я делаю что-то не так, когда 'внешний' регистратор является членом класса:

(DLL не изменяется)

Клиент:

class OuterLogger
{
public:
    OuterLogger();
    ~OuterLogger();

    void logFunction(const std::string& message, int level);
};

void OuterLogger::logFunction(const std::string& message, int level)
{
    // display/save messages
}

main()
{
    OuterLogger outerLogger;
    std::function<void(const std::string& message, int level)> logFunctionPtr = outerLogger.logFunction;
    setLoggingFunction(logFunctionPtr);
}

Ответы [ 2 ]

0 голосов
/ 04 октября 2019

Я пробовал несколько разных способов передачи указателя на функцию, ни одна из которых не сработала, НО оказалось, что с этим кодом все в порядке.

Когда я использовал код любой формы, который был успешно принят DLL-регистратором, отладка показала, что впоследствии он сразу же обнулится.

Я использую Тестовый проводник VS '. Оказывается, некоторые тестируемые экземпляры процессов не закрывались должным образом, поэтому я поместил процессы тестового хоста в фоновом режиме, и я думаю, что адреса как-то испортились.

Подсказки заключались в периодической неспособности выполнить тест более одного раза и очень странном поведении в режиме отладки - маркер выполнения возвращался назад и пропускал все вокруг, создавая загадочные исключения WINRT_ASSERT (! Is_sta ()). Ответ - запустить Process Explorer и проверить, не застряли ли процессы под VS. (немного раздражает, что VS не может сказать мне, что была проблема с процессом, который он тестировал, но nvm)

Мой код использует библиотеку WinML. Если я бегу в режиме процессора, это нормально. Если я использую графический процессор, он зависает при выключении, поэтому мне нужно выяснить, почему.

Спасибо всем за помощь.

Редактировать: мое первоначальное предположение в моем вопросе состояло в том, что это была проблема при перемещении кода от необъекта к объекту - это было совершенно неправильно. Первоначальная необъектная версия кода работала, потому что она была в демо-клиенте, единственной исполняемой консольной программе, вызывающей DLL, на которую никогда не влияла хитрая проблема завершения работы. В модульном тесте с несколькими экземплярами это стало проблемой.

0 голосов
/ 02 октября 2019

Вот пример того, как класс может быть привязан к функции:

#include <iostream>
#include <functional>

class A {
    public:
    int x = 1;
    void func() {
        std::cout << x;
    }
    ~A() {
        x = 2; // just to test the destructor
    }
};

int main()
{
    std::function<void(void)> f;

    {
        A a;
        f = std::bind(&A::func, a); // do not bind &a because it will be out of scope
    }

    f();

    return 0;
}

В вашей ситуации вы можете использовать:

std::function<void(const std::string& message, int level)> logFunctionPtr = std::bind(&OuterLogger::logFunction, outerLogger, std::placeholders::_1, std::placeholders::_2);

Вместо привязки вы можете использоватьлямбда-функция:

std::function<void(const std::string&, int)> logFunctionPtr =
    [outerLogger](const std::string& message, int level) mutable {
        outerLogger.logFunction(message, level);
    };
...