Calling Win32 api via C # fails!

I have a C ++ function exported as api like this:

#define WIN322_API __declspec(dllexport)
WIN322_API char* Test(LPSTR str);
WIN322_API char* Test(LPSTR str)
{
 return "hello";
}

the function is exported as an API correctly using the .DEF file, because I can see it in the Dependency Walker tool. Now I have a C # testers program:

[DllImport("c:\\win322.dll")]

public static extern string Test([MarshalAs(UnmanagedType.LPStr)] String str);

private void Form1_Load(object sender, EventArgs e)
        {
string _str = "0221";
Test(_str); // runtime error here!

}

when calling the Test () method, I get an error:

"Calling the PInvoke Function" MyClient! MyClient.Form1 :: Test "has an unbalanced stack. This is probably because the PInvoke managed signature does not match the unmanaged target signature. Make sure the calling convention and PInvoke signature settings match the target unmanaged signature."

I tried many other data types and marshals, but received nothing! Plz help me!

+3
source share
6

, . DLL Cdecl, # - StdCall. .

, Windows, ANSI char (, A W), CharSet, .

, . , . , () .

, , :

[DllImport("c:\\win322.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string Test([MarshalAs(UnmanagedType.LPStr)] String str);
+1

, [DllImport] Stdcall, C- Cdecl. CallingConvention .

, , Vista Win7. C , . , . , . malloc() free(). , pinvoke , , C.

Marshal.FreeCoTaskMem(). , CoTaskMemAlloc(). XP , . kaboom Vista Win7, .

C :

extern "C" __declspec(dllexport) 
void __stdcall Test(const char* input, char* output, int outLen);

, , , . StringBuilder #.

[DllImport("foo.dll")]
private static extern void Test(string input, StringBuilder output, int outLen);
...
    var sb = new StringBuilder(666);
    test("bar", sb, sb.Capacity);
    string result = sb.ToString();

, outLen C, . , Fatal Execution Engine.

+5

#define WIN322_API __declspec(dllexport) __stdcall

CallingConvention.Cdecl .

, , .

+2

Try returning LPSTR, not char *. You may also need to specify the stdcall calling convention, which is used by default in .NET, but I'm not sure about your unmanaged project.

0
source

Use Unmanagedtype.LPTStr for input. Pay attention to the extra T

[MarshalAs(UnmanagedType.LPStr)] String str  // your current code
[MarshalAs(UnmanagedType.LPTStr)] String str // try this code
0
source

Pass StringBuilder from .Net as parameter, not returning string (in this case it will be as out parameter)

0
source

Source: https://habr.com/ru/post/1783204/


All Articles