Иногда невозможно получить доступ к источнику по умолчанию для gem, https://rubygems.org/
.
Он должен быть удален командой:
gem sources -r https://rubygems.org/
И тогда новый источник должен добавлен:
gem sources -a https://ruby.taobao.org/
Обновить кеш:
gem sources -u
Вы можете проверить источники с помощью:
gem sources
Наконец, вы можете установить cocoapods
:
sudo gem install cocoapods
Как возвращается значение независимо от используемого языка. Он определяется только вызывающей сигнатурой функции. Поэтому я мог написать следующий источник DLL в C ++:
#include <windows.h>
BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
)
{
return TRUE;
}
__declspec(dllexport) char *function1()
{
char *foo = new char[100];
// do stuff to fill in foo
return foo;
}
__declspec(dllexport) void function2(char *out, int maxOutSize)
{
// do stuff to fill in out
}
, который является полностью законным, и определяет точки входа C ++ с сигнатурами, которые точно соответствуют обеим функциям, перечисленным в вопросе OP.
Обратите внимание, что это использует C ++ new[]
для выделения памяти для function1()
, поэтому необходимо будет ее освободить в какой-то момент, используя delete[]
.
В том же ключе, если память выделенные CLR в случае C #, вам нужно либо передать его обратно в C # DLL, чтобы он был правильно выпущен, либо найти безопасный способ уничтожить его на C ++, предполагая, что такая операция даже возможна.
Я буду на 100% честным здесь и скажу, что у меня нет никакой подсказки, если C ++ runtime и C # CLR будут хорошо играть вместе с распределением памяти. Таким образом, может быть, что единственный вариант - передать его обратно на C # для освобождения.
- Изменить -
Я собираюсь связать этот вопрос также для дальнейшей ссылки , поскольку он имеет дело с другим взглядом на ту же проблему, и, в частности, принятый ответ содержит в себе чрезвычайно полезную информацию.
Передача строк из C # в C ++ DLL и обратно - минимальный пример
Я предполагаю, что причина такова:
Когда вы вызываете c # api из c ++, вы вызываете код, управляемый виртуальной машиной CLR, поэтому распределение памяти автоматически управляется самой виртуальной машиной, что позволяет вам не беспокоиться о распределении буфера вручную.
Я не понимаю, как C # callle может выделить память, где C ++ вызываемый не смог?
Вы ищете неправильную проблему , Проблема не в том, «как C # может выделить память». Любой может выделить память ... И слишком много способов :-) Проблема всегда «как вы освободите память?», Потому что освобождение памяти так же важно, как выделение памяти (не освобождение памяти приведет к памяти утечки, которые сделают ваше занятие памятью программы пройденным шаром, а освобождение его с помощью неправильного распределителя не освободит его как минимум (см. предыдущую точку) и в худшем случае приведет к сбою программы ).
Теперь ОС (например, Windows) дает вам некоторые распределители (например, CoTaskMemAlloc
), которые может использовать любой пользователь, но проблема в том, что обычно в C / C ++ вы используете, Используйте malloc
/ new
. И проблема здесь: эти распределители могут быть «разными» (отдельными) между двумя dll: две библиотеки dll, скомпилированные в C / C ++ (но, например, с разными версиями Visual C ++ или в режиме отладки vs release или один с использованием среды выполнения как dll, а другая, связанная непосредственно с исполняемой средой или скомпилированная с разными компиляторами C), будет иметь различные malloc
(и различные new
в C ++). Имея различные malloc
/ new
, они будут иметь free
/ delete
, так что free
одной dll не может освободить память другой dll.
Теперь ... Используя эту подпись:
void MyCPPDllFunction(char *out, int maxOutSize);
вызывающий должен выделить память ... Таким образом, вызывающий пользователь знает, как освободить память ... Нет утечки памяти: -)
С помощью этой сигнатуры:
char *MyCPPDllFunction();
вызываемому приходится выделять память ... А теперь как может вызывающий ее освободить? Вызов может экспортировать другой метод:
void FreeMemoryAllocatedByMe(void *ptr)
{
free(ptr);
}
, после чего вызывающий абонент вызовет его, и все будет решено, потому что free
будет вызываемым free
.
Теперь ... В общем случае, когда объекты (и строки) C # -маршалов, он использует CoTaskMemAlloc
для выделения памяти, и ожидает, что если он получит память, он должен освободить ее с помощью CoTaskMemFree
, Итак, в примере C ++ -> C # C ++ должен
CoTaskMemFree(output);
free()
из C ++, я был бы очень подозрительным к любой попытке, которая использует среду выполнения одного языка для выделения памяти, а также для запуска другого языка для ее освобождения. – dgnuff 13 July 2018 в 07:09