Как передать строку из c (общая библиотека, *.so) в c# в Linux

#c# #c #interop

#c# #c #взаимодействие

Вопрос:

Не удалось повторить строку

C :

 #include lt;iostreamgt; #include lt;newgt;  #include lt;cstringgt; extern "C" {  int DataToDotNet(char* str, uint64_t amp;size); }  int DataToDotNet(char* str, uint64_t amp;size){  size = 8;  str = new char[size];  std::strcpy(str, "CString");  std::cout lt;lt; "Sent Value is " lt;lt; str lt;lt; 'n';  return 1; }  

C#:

 using System; using System.Text; using System.Runtime.InteropServices;    namespace DotNetConsole {  class Program  {  [DllImport("1.so",CallingConvention=CallingConvention.Cdecl)]  private static extern int DataToDotNet([MarshalAs(UnmanagedType.LPStr)]StringBuilder str, ref ulong size);    static void Main(string[] args)  {  StringBuilder str= new StringBuilder();  ulong size = 0;  int k=DataToDotNet(str,ref size);  Console.WriteLine(str.Length.ToString());//Prints 0  }  } }  

Также я использую ref(C#) и amp;(C ) для базового типа, есть ли лучший способ? Я не использую visual C . ОС-это Linux. Команда компилятора:

 clang   -pedantic-errors -Wall -Wextra -Weffc   -Wsign-conversion -Werror -std=c  17 -fPIC -c -o 1.o 1.cpp  clang   -pedantic-errors -Wall -Wextra -Weffc   -Wsign-conversion -Werror -std=c  17 -shared -v -o 1.so 1.o  

Я поместил файл в net5 папки отладки. Любые ссылки/ссылки/советы по этой теме также приветствуются[Примечание: Я использую Linux, .Net 5, а не visual c ]

Комментарии:

1. Вместо всех этих назначений, почему бы и нет std::strcpy(str, "CString"); ? И вместо вызова функции new почему бы не использовать обычный new[] , как в str = new char[size]; ?

2. Что касается одной серьезной проблемы, вы, кажется, забыли, что аргументы в C по умолчанию передаются по значению . Это означает, что значение, используемое в вызове, копируется в локальную переменную аргумента функции. Поэтому, когда вы назначаете str себе, вы изменяете только локальную переменную str . Исходное значение, используемое при вызове функции, не будет изменено. Вам нужно пройти по ссылке (как вы это делаете для size ).

3. И вам, вероятно, нужно использовать extern "C" для этой функции, чтобы предотвратить искажение имени.

4. лол, я использовал мэллока. Я использую extern, у меня он работал для типа char. Я понимаю, что для передачи строк требуется немного больше работы, чем для передачи символов.

5. Только extern или extern "C" ? Это две совершенно разные вещи. Вам нужно определить функцию как extern "C" int DataToDotNet(char* str, uint64_t amp;size){ ... } .