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

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

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:

  1. > d^¡Aè☺

Here is my C++ code:

  1. #include "pch.h"
  2. #include<stdio.h>
  3. #include<Windows.h>
  4. #include<string>
  5. using namespace System;
  6. using namespace System::Runtime::InteropServices;
  7. using namespace System::Reflection;
  8. int main()
  9. {
  10. const char* pemodule = ("C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll");
  11. HMODULE hlib = LoadLibraryA(pemodule);
  12. typedef int(__cdecl *add)(int a, int b);
  13. typedef int(__cdecl* AntiMacro)(std::string path);
  14. auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");
  15. std::string path = "C:\\macro\\test";
  16. int a = pAntiMacro(path);
  17. printf("%d\n", a);
  18. return 0;
  19. }

And here is my C# DLL:

  1. [DllExport]
  2. public static int AntiMacro(string filepath)
  3. {
  4. Console.WriteLine(filepath);
  5. bool isFolder = false;
  6. string fullpath = "";
  7. try
  8. {
  9. fullpath = Path.GetFullPath(filepath);
  10. Console.WriteLine(fullpath.ToString());
  11. }
  12. catch (Exception)
  13. {
  14. Console.WriteLine(fullpath);
  15. Console.WriteLine("Invalid path 1");
  16. return 1;
  17. }

I tried to change

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

to

  1. 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:

  1. #include "pch.h"
  2. #include<stdio.h>
  3. #include<Windows.h>
  4. #include<string>
  5. using namespace System;
  6. using namespace System::Runtime::InteropServices;
  7. using namespace System::Reflection;
  8. int main()
  9. {
  10. const char* pemodule = ("C:\\Users\\source\\repos\\ClassLibrary2\\ClassLibrary2\\bin\\Debug\\ClassLibrary2.dll");
  11. HMODULE hlib = LoadLibraryA(pemodule);
  12. typedef int(__cdecl *add)(int a, int b);
  13. typedef int(__cdecl* AntiMacro)(std::string path);
  14. auto pAntiMacro = (AntiMacro)GetProcAddress(hlib, "AntiMacro");
  15. std::string path = "C:\\macro\\test";
  16. int a = pAntiMacro(path);
  17. printf("%d\n", a);
  18. return 0;
  19. }

And here is my C# DLL:

  1. [DllExport]
  2. public static int AntiMacro(string filepath)
  3. {
  4. Console.WriteLine(filepath);
  5. bool isFolder = false;
  6. string fullpath = "";
  7. try
  8. {
  9. fullpath = Path.GetFullPath(filepath);
  10. Console.WriteLine(fullpath.ToString());
  11. }
  12. catch (Exception)
  13. {
  14. Console.WriteLine(fullpath);
  15. Console.WriteLine("Invalid path 1");
  16. return 1;
  17. }

I tried to change

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

to

  1. 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*

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

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

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPStr)]
  4. string filepath)
  5. {

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

英文:

You first need to convert std:string into char*

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

You also need marshalling for the string

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPStr)]
  4. string filepath)
  5. {

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所说:我需要将这段代码放入我的代码中:

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPStr)]
  4. string filepath)
  5. {

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

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPUTF8Str)]
  4. string filepath)

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

英文:

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

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPStr)]
  4. string filepath)
  5. {

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

  1. [DllExport]
  2. public static int AntiMacro(
  3. [MarshalAs(UnmanagedType.LPUTF8Str)]
  4. 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:

确定