использование map в C ++ и предоставление функций-оболочек для использования в C

В MSVC6 мне нужно использовать map в C ++ и предоставлять функции-оболочки, чтобы использовать их в c только для добавления, удаления и получения размера. Я хочу сделать это без использования каких-либо классов в C ++. Это будет использоваться потоками, каждый поток будет иметь дескриптор структуры, который будет иметь void * который будет передан в качестве параметра в функции оболочки C ++, и я хочу, чтобы код C ++ преобразовал это void * на карту и делать операции. Я не могу конвертировать void * к карте в C ++ было бы полезно любое решение.

-1

Решение

Я попробую, потому что мне нравится гадать:

Я предполагаю, что у вас есть функция, которая передается в функцию create thead, которая выглядит примерно так:

int callback(void* userdata);

Итак, давайте сделаем функцию обратного вызова для доступа к карте:

// In the header file: "my_callback.h" we first need to declare that this function will be used from a C file, this is so the compiler will name the function according to the C standard and not C++.
#ifdef __cplusplus
extern "C" {
#endif

// Declare your function:
int my_callback(void * map_handle);

#ifdef __cplusplus
extern "C" {
#endif

Теперь, в файле c ++, убедитесь, что вы включили заголовочный файл:

#include "my_callback.h"
int my_callback(void * map_handle) {
// First, for convenience, let us define the map type
using mapType = std::map<std::string, int>;

// First cast the void * to a the correct map * pointer
mapType *mapPtr = static_cast<mapType*>(map_handle);

mapPtr->insert( "Test", 1 ); // Insert
cout << (*mapPtr)["Test"];   // read

// Or you can assign it to a reference to hide away the pointer syntax:
mapType & mapRef = *static_cast<mapType*>(map_handle);mapRef.insert( "Test", 1 ); // Insert
cout << mapRef["Test"];   // read

// (...)
}

Есть несколько вещей, которые стоит отметить:

  1. Нам разрешено использовать static_cast потому что вход является void Указатель, вы должны передавать адрес целевой карты, когда вы создаете поток, и статическое приведение к и затем из пустого указателя на тот же тип хорошо определено.

  2. Это никоим образом не потокобезопасно. Особое внимание должно быть уделено при доступе тот же самый ресурс из нескольких потоков одновременно. Если вы намереваетесь иметь только одну карту и разрешить всем потокам обращаться к ней, вы должны включить мьютекс, чтобы гарантировать, что за один раз к нему обращается только один поток. Отличный способ сделать это — просто создать небольшую структуру, включающую карту и мьютекс:

    struct map_n_mutex {
    mapType map;
    some_mutex_t mutex; // Не уверен, какой будет правильный тип мьютекса в Windows.
    };

На этапе инициализации вашего потока:

// Create map
map_n_mutex user_data;

// Create thread (I'm making this function up, use what you have been using)
create_thread( my_callback, &user_data); // pass a pointer to userdata

Если вы придерживаетесь этого подхода, помните, что вам нужно map_n_mutex и не mapType внутри функции обратного вызова.

0

Другие решения

Код C нужно будет получить void указатель из кода C ++, делает что-то вроде

void *get_map_from_cpp();   /* declare the function */

void *our_map = get_map_from_cpp();

где get_map_from_cpp() будет определен (в C ++) как что-то вроде;

 #include <map>
#include <string>

extern "C" void *get_map_from_cpp()
{
std::map<std::string, float> *the_map = new std::map<std::string, float>;
return static_cast<void *>(the_map);
}

Это не останавливается там все же. Чтобы вставить значения в карту, нам нужно передать значения, например, в C

  void insert_to_map(void *, const char *str, float f);   /* declaration */

insert_to_map(our_map, "Everything", 42.0);

где insert_to_map() также должен быть определен в C ++, например как

   extern "C" void insert_to_map(void *m, const char *str, float f)
{
std::map<std::string, float> *the_map;

the_map = static_cast< std::map<std::string, float> *>(m);
std::string the_str(str);
(*the_map)[the_str] = f;
}

Точно так же, retrieve_from_map() может быть реализовано как

 extern "C" float retrieve_from_map(void *m, const char *str)
{
std::map<std::string, float> *the_map;

the_map = static_cast< std::map<std::string, float> *>(m);
std::string the_str(str);

std::map<std::string, float>::const_iterator i = the_map->find(the_str);
if (i != the_map->end())
return i->second;
else
return 0.0f;     // string not found in map, so return 0.0
}

Функции, вызываемые из C, должны предоставлять интерфейс только для C — это означает, что код C не может напрямую касаться типов C ++. Во-вторых, сопоставление с C ++ должно выполняться исключительно в коде C ++, поскольку компилятор C не будет понимать конструкции. Это означает, что функции должны принимать или возвращать только те типы, которые имеют смысл в C, функции должны быть объявлены как extern "C" для компилятора C ++ (чтобы их можно было вызывать из C), а тело функции должно обрабатывать отображение типов C в C ++.

Это зависит от совместимости компиляторов C и C ++ (например, от одного поставщика, совместимого ABI и т. Д.).

0

По вопросам рекламы [email protected]