Почему в моем коде возникает ошибка, когда в учебнике, который я использовал, вообще нет ошибки?

Я следовал этому руководству посимвольно, но по какой-то причине получаю следующую ошибку :

" 1> c:\users\fish's ocean\source\repos\dll1\dll1\dll1.cpp(47): ошибка C2664: 'bool (ds_map,char *,double)': невозможно преобразовать аргумент 2 из 'const char [ 5]' в 'символ *'"

также в строках 48 и 49.

Вот как выглядит моя Visual Studio в этих строках, но по какой-то причине туториал у него нет ошибки, и я не могу понять разницу (он переходит эти строки где-то на 17-й минуте)

// Dll1.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>

#define gmx extern "C" __declspec(dllexport)

using ds_map = int;
using thread = std::thread;
using milliseconds = std::chrono::milliseconds;

const int EVENT_OTHER_SOCIAL = 70;

void(*gml_event_perform_async)(ds_map map, int event_type) = nullptr;
int(*gml_ds_map_create)(int n, ...) = nullptr;
bool(*gml_ds_map_add_double)(ds_map map, char* key, double value);
bool(*gml_ds_map_add_string)(ds_map map, char* key, char* value);

std::mutex thread_key;

std::vector<thread*> threads;
std::vector<uint32_t> open_slots;

gmx double RegisterCallbacks(char * arg1, char* arg2, char* arg3, char* arg4) {
gml_event_perform_async = (void(*)(ds_map, int))arg1;
gml_ds_map_create = (int(*)(int, ...))arg2;
gml_ds_map_add_double = (bool(*)(ds_map, char*, double))arg3;
gml_ds_map_add_string = (bool(*)(ds_map, char*, char*))arg4;
return 0;
}

ds_map ds_map_create() {
return gml_ds_map_create(0);
}

void return_double(double time, double type, double value, int handle) {
long t = (long)time;
std::this_thread::sleep_for(milliseconds(t));

thread_key.lock();

ds_map map = ds_map_create();
gml_ds_map_add_double(map, "type", type);
gml_ds_map_add_double(map, "value", value);
gml_ds_map_add_double(map, "handle", handle);
gml_event_perform_async(map, EVENT_OTHER_SOCIAL);

thread_key.lock();
}

gmx double thread_create(double time, double type, double value) {
int index;

thread_key.lock();

if (open_slots.empty()) {
    index = threads.size();
    threads.push_back(new thread(return_double, time, type, value, index));
}
else {
    index = open_slots.back();
    open_slots.pop_back();
    threads[index] = new thread(return_double, time, type, value, index);
}

thread_key.unlock();
return index;
}

gmx double thread_kill(double index) {
thread_key.lock();

if (threads.size() > index && threads[index] != NULL) {
    if (threads[index]->joinable()) {
        threads[index]->detach();
    }
    delete threads[index];
    threads[index] = NULL;
    open_slots.push_back(index);
}
thread_key.unlock();
return 1;
}

gmx double thread_free(double index) {
thread_key.lock();

if (threads.size() > index && threads[index] != NULL) {
    if (threads[index]->joinable()) {
        threads[index]->join();
    }
    delete threads[index];
    threads[index] = NULL;
    open_slots.push_back(index);
}
thread_key.unlock();
return 1;
}

person Dylan Wolfer    schedule 12.03.2019    source источник
comment
Создайте минимально воспроизводимый пример   -  person eerorika    schedule 12.03.2019
comment
Я бы сказал, что объявления gml_ds_map_add_double и ..._add_string должны иметь const char* в качестве второго аргумента. Но я не знаю библиотеку, поэтому не знаю, правильно ли это.   -  person Nico Schertler    schedule 12.03.2019
comment
Это вызывает 1›c:\users\fish's ocean\source\repos\dll1\dll1\dll1.cpp(31): ошибка C2440: '=': невозможно преобразовать из 'bool (__cdecl *)(ds_map,char *,double )' на 'bool (__cdecl *)(ds_map,const char *,double)' (и аналогичная ошибка в строке 32)   -  person Dylan Wolfer    schedule 12.03.2019
comment
Это вопрос корректности const. Вы не можете удалить const: то есть вы не можете преобразовать const char * в char *, потому что тогда вы можете изменить его, тем самым нарушив const.   -  person Cruz Jean    schedule 12.03.2019


Ответы (1)


Казалось бы, ваш учебник древний. Давным-давно некоторые компиляторы позволяли передавать строку символов - "type" параметру, который хотел char *, или присваивать эти значения переменной char *. (Символьные строки не рассматривались как константы.)

Это было изменено, чтобы строки символов были постоянными (и только для чтения). Это означает, что большинство (если не все) ваших char * параметров в функциях, указателях функций и прототипах необходимо изменить на const char *, чтобы работать с строками символов, которые вы используете. Однако это будет означать, что функции, используемые в качестве обратных вызовов, также должны будут изменить свои подписи.

И RegisterCallbacks должен брать правильные прототипы функций для всех параметров, а не принимать их как char * значения. В наши дни броски, необходимые для этого, могут легко привести к неопределенному поведению.

person 1201ProgramAlarm    schedule 12.03.2019