开发者

Strings in c++?

开发者 https://www.devze.com 2023-04-11 04:58 出处:网络
My problem is , i have some functions in a DLL some of these functions are for example : #include <string>

My problem is , i have some functions in a DLL some of these functions are for example :

#include <string>
using namespace std;
extern "C" __declspec(dllexport) string __cdecl encryption(string s)
{
 return s;
}

Whenever i try to call this function from C# , here is the code im using :

[DllImport("Packer.dll", EntryPoint = "encryption")]
static extern string encryption(string s);

i get an error : A call to PInvoke function 'Packer' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged sig开发者_高级运维nature.

im guessing i get this error because i dont have the right declarations for the function can anyone guide me how to fix that , thanks in advance


std::string can not be used with PInvoke, because C++ does not have an ABI for its objects which is required to properly clean stack, copy objects, etc. This is one of the greatest pains of C++.

You have to use char* pointers and plain C APIs. Simply put, PInvoke does not work with C++.


As I'm sure you already know, the C++ std::string is actually a template. Only when the template is instantiated (as std::basic_string<char> in this case), the exact layout of the objects of that type and signatures of the methods are determined by the C++ compiler.

Unfortunately, only the C++ compiler in question has the access to all the relevant information (such as template source code) to make these kinds of decisions. That's why non-C features such as templates are generally not "transferable" even between different C++ compilers, let alone C++ and C#.

Also, C++ names are typically "mangled" in a C++ compiler-specific manner.

You'll have to change the signature of your native method, so it is becomes a "pure" C function:

  • Ensure there is no C++ name mangling by declaring the function as extern "C" (you are already doing that).
  • Use char* parameter instead of std::string.
  • Return char* result instead of std::string, but be very careful how you do it.
  • Ensure your DllImportAttribute.CallingConvention matches the __cdecl, __stdcall or __fastcall in your C.


The problem here is, you're using the STL string class which C# doesn't know how to marshal. You have two options here:

  1. refactor your C++ code to work with char * buffers. Or write a wrapper or an overload or something that uses char * instead of string.
  2. Write a C++/CLI wrapper around your C++ functions that uses System::String and calls the STL string versions internally.


If memory serves, if you don't specify otherwise P/Invoke assumes the calling convention is __stdcall. If so, changing your __cdecl to __stdcall should fix the first problem. As @Adam Rosenfield points out, you probably also need to pass and return a char const *, not a string. C# and C++ almost certainly have somewhat different ideas of what constitutes a string.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号