无法将字符串从C++解析到C#。

huangapple go评论77阅读模式
英文:

Can not parse a string from C++ to C#

问题

I write a C# dll and call it from C++ function. But when I parse a string from C++ to C# function, I will show something weird like this:

> d^¡Aè☺

Here is my C++ code:

#include "pch.h"
#include<stdio.h>
#include<Windows.h>
#include<string>

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;

int main()
{
	const char* pemodule = ("C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll");
	HMODULE hlib = LoadLibraryA(pemodule);
	typedef int(__cdecl *add)(int a, int b);

	typedef int(__cdecl* AntiMacro)(std::string path);
	auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");

	std::string path = "C:\\macro\\test";
	int a = pAntiMacro(path);
	printf("%d\n", a);
    return 0;
}

And here is my C# DLL:

[DllExport]
public static int AntiMacro(string filepath)
{
    Console.WriteLine(filepath);
    bool isFolder = false;
    string fullpath = "";
    try
    {
        fullpath = Path.GetFullPath(filepath);
        Console.WriteLine(fullpath.ToString());
    }
    catch (Exception)
    {
        Console.WriteLine(fullpath);
        Console.WriteLine("Invalid path 1");
        return 1;
    }

I tried to change

std::string path = "C:\\macro\\test"

to

const char *path = "C:\\macro\\test"

But it still not working, is that string in C++ is different from C#?

英文:

I write a C# dll and call it from C++ function. But when i parse a string from C++ to C# function, i will show something weird like this:
> d^¡Aè☺

Here is my C++ code:

#include "pch.h"
#include<stdio.h>
#include<Windows.h>
#include<string>

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Reflection;

int main()
{
	const char* pemodule = ("C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll");
	HMODULE hlib = LoadLibraryA(pemodule);
	typedef int(__cdecl *add)(int a, int b);

	typedef int(__cdecl* AntiMacro)(std::string path);
	auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");

	std::string path = "C:\\macro\\test";
	int a = pAntiMacro(path);
	printf("%d\n", a);
    return 0;
}

And here is my C# DLL:

[DllExport]
        public static int AntiMacro(string filepath)
        {
            Console.WriteLine(filepath);
            bool isFolder = false;
            string fullpath = "";
            try
            {
                fullpath = Path.GetFullPath(filepath);
                Console.WriteLine(fullpath.ToString());
            }
            catch (Exception)
            {
                Console.WriteLine(fullpath);
                Console.WriteLine("Invalid path 1");
                return 1;
            }

I tried to change

std::string path = "C:\\macro\\test"

to

const char *path = "C:\\macro\\test"

But it still not working, is that string in C++ is different from C#?

答案1

得分: 3

你首先需要将 std::string 转换为 char*

std::string path = "C:\\macro\\test";
const char *cstr = path.data();
int a = pAntiMacro(cstr);

你还需要为字符串进行编组

[DllExport]
public static int AntiMacro(
  [MarshalAs(UnmanagedType.LPStr)]
  string filepath)
{

但使用 C++/CLI 可能是更好的选择。

英文:

You first need to convert std:string into char*

std::string path = "C:\\macro\\test";
const char *cstr = path.data();
int a = pAntiMacro(cstr);

You also need marshalling for the string

[DllExport]
public static int AntiMacro(
  [MarshalAs(UnmanagedType.LPStr)]
  string filepath)
{

But using C++/CLI might be a better option either way.

答案2

得分: 2

To work with C# DLLs in C++, you need to use the .NET Framework's Common Language Runtime (CLR) and interact with the DLL through managed interop: https://learn.microsoft.com/en-us/cpp/dotnet/overview-of-marshaling-in-cpp?view=msvc-170

Also see this: https://stackoverflow.com/questions/3539334/how-to-turn-systemstring-into-stdstring https://stackoverflow.com/a/53016935/5033623

I highly do not recommend this approach though unless you have a very specific reason to work with C# API calls in your native application. It's usually the other way around.

英文:

To work with C# DLLs in C++, you need to use the .NET Framework's Common Language Runtime (CLR) and interact with the DLL through managed interop:
https://learn.microsoft.com/en-us/cpp/dotnet/overview-of-marshaling-in-cpp?view=msvc-170

Also see this:
https://stackoverflow.com/questions/3539334/how-to-turn-systemstring-into-stdstring
https://stackoverflow.com/a/53016935/5033623

I highly do not recommend this approach though unless you have a very specific reason to work with C# API calls in your native application. It's usually the other way around.

答案3

得分: 0

UPDATE: 我找到了解决方案。正如Charlieface所说:我需要将这段代码放入我的代码中:

[DllExport]
public static int AntiMacro(
  [MarshalAs(UnmanagedType.LPStr)]
  string filepath)
{

但仍然无法正常工作,所以我稍微修改了它:

[DllExport]
public static int AntiMacro(
  [MarshalAs(UnmanagedType.LPUTF8Str)]
  string filepath)

我将UnmanagedType.LPStr更改为UnmanagedType.LPUTF8Str,它完美运行。并根据Charlieface提供的建议编辑了我的C++代码。

英文:

UPDATE: i found the solution. As Charlieface said: i need to put this in my code:

[DllExport]
public static int AntiMacro(
  [MarshalAs(UnmanagedType.LPStr)]
  string filepath)
{

But it still not working, so i rewrite it a little bit:

    [DllExport]
    public static int AntiMacro(
      [MarshalAs(UnmanagedType.LPUTF8Str)]
      string filepath)

I change UnmanagedType.LPStr to UnmanagedType.LPUTF8Str and it work perfectly. And edit my C++ code as Charlieface provided.

huangapple
  • 本文由 发表于 2023年6月13日 18:48:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76464109.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定