Не получается передать строку или ее адрес в памяти из dll C++ в клиент C#, только char или int
Как передавать что то большее чем char или int, например строку?, через указатель на область памяти не получается: состав dll: file string_emplary.cpp
#include "pch.h"
#include "string_emplary.h"
#include <iostream>
char* Emplary()
{
char dest[8];
const char* b = &"Emplary"[0];
strcpy(dest, b);
return dest;
}
int* int_a(){ int a = 10; int* p = &a; return p; }
int int_b(){ int b = 357; return b;}
char char_c(){ char c = 'c'; return c;}
file string_emplary.h
#pragma once
#ifdef string_emplary
#define string_emplary_API __declspec(dllexport)
#else
#define string_emplary_API __declspec(dllimport)
#endif
extern "C" string_emplary_API char* Emplary();
extern "C" string_emplary_API int* int_a();
extern "C" string_emplary_API int int_b();
extern "C" string_emplary_API char char_c();
принимающая сторона C# file Form1.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace import_from_cppdll
{
public unsafe partial class Form1 : Form
{
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern char* Emplary();
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int* int_a();
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int int_b();
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern char char_c();
public Form1()
{
InitializeComponent();
}
private unsafe void button1_Click(object sender, EventArgs e)
{
char p0 = *Emplary(); // garbage
char p1 = ++*(Emplary()); // garbage
char p2 = ++*(Emplary());// garbage
int a0 = *int_a(); // garbage
int* a1 = int_a();//
char* p00 = Emplary(); // here at the address is '\0'
int b0 = int_b(); // 357 !!! it work!
char c0 = char_c(); // 99'c' !!! it work!
}
}
}
Ответы (3 шт):
Автор решения: cup
→ Ссылка
Это ответ на закрытое сообщение: вот оно. Проблема в том, что символы C ++ составляют 1 байт, а символы C# - 2 байта. Чтобы обойти это, используйте wchar_t в своей программе на C.
extern "C"
{
wchar_t dest[8]; /* return value must not be on the stack */
string_emplary_API wchar_t* Emplary()
{
/* Wide string literals have a leading L */
const wchar_t* b = L"Emplary";
/* This is the wide string version of strcpy */
wcscpy(dest, b);
/* This value must not be on the stack */
return dest;
}
}
Автор решения: 110010100
→ Ссылка
Благодаря @cup окончательно все поправил:
dll: file string_emplary.cpp
#include "pch.h"
#include "string_emplary.h"
#include <iostream>
#include <string>
void FillArrayInt(int a[], int n)
{
const char* b = &"Emplary"[0];
for (size_t i = 0; i < n; i++)
{
a[i] = b[i];
}
}
wchar_t* Emplary (wchar_t dest[])
{
/* Wide string literals have a leading L */
const wchar_t* b = L"Emplary";
/* This is the wide string version of strcpy */
wcscpy(dest, b);
/* This value must not be on the stack */
return dest;
}
file string_emplary.h
#pragma once
#ifdef string_emplary
#define string_emplary_API __declspec(dllexport)
#else
#define string_emplary_API __declspec(dllimport)
#endif
extern "C" string_emplary_API void FillArrayInt(int a[], int n);
extern "C" string_emplary_API wchar_t* Emplary(wchar_t dest[]);
C# file Form1.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace import_from_cppdll
{
public unsafe partial class Form1 : Form
{
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void FillArrayInt(int[] a, int n);
[DllImport(@"D:\VLAD\C++\import_DLL\string_emplary\Debug\string_emplary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern char* Emplary(char[] incoming);
public Form1()
{
InitializeComponent();
}
private unsafe void button1_Click(object sender, EventArgs e)
{
int b = 8;
int[] a = new int[8];
FillArrayInt(a, b);
string output = "";
for (int i = 0; i < 8; ++i)
{
output += Convert.ToChar(a[i]); // "Emplary\0" it work!!!
}
var incoming = new char[8];
char* outBuf = Emplary(incoming);
for (int i = 0; i < incoming.Length; i++)
{
incoming[i] = outBuf[i];
}
// it work!!!
}
}
}
Автор решения: 110010100
→ Ссылка
ЭТО НЕ ОТВЕТ , А вопрос где здесь утечка памяти?? =) - I thought that in C# automatic garbage collection
