DefinePInvokeMethod causing PInvokeStackImbalance when returning a value from the native function ca

M

Marek

Hi
I'm trying to call a native C++ dll using the following code (both C# and
C++ code segments included). When I make the call to the method
(AddTwoDoubles) that has no return value all is fine. When I try and call a
function that returns a double (AddTwoDoubles2) I get the following message:


PInvokeStackImbalance was detected
Message: A call to PInvoke function 'tempModule!<Module>::AddTwoDoubles2'
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 signature.

I can't see what I'm doing wrong.

Thanks for any help that anyone can provide.

Marek
=====================================================================
C# code follows.
=====================================================================
//...Set up the return value:
//Type returnType = null; //...Function (AddTwoDoubles) with void return
works
Type returnType = typeof(double); //...Function (AddTwoDoubles2) does not
work

//...Set up the parameters:
Type[] parameterTypes = new Type[2];
object[] parameterValues = new object[2];

parameterTypes[0] = typeof(double);
parameterValues[0] = 2.0;
parameterTypes[1] = typeof(double);
parameterValues[1] = 2.0;

// Create a dynamic assembly and a dynamic module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder.DefineDynamicModule("tempModule");

// Dynamically construct a global PInvoke signature using the input
information
MethodBuilder methodBuilder =
moduleBuilder.DefinePInvokeMethod(entryPointName, dllName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl, CallingConventions.Standard, returnType,
parameterTypes, CallingConvention.Winapi, CharSet.Ansi);

moduleBuilder.CreateGlobalFunctions();

// Get a MethodInfo for the PInvoke method
MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);

// Invoke the static method and return whatever it returns
ParameterInfo[] parameterInfo = methodInfo.GetParameters();

try
{
Object returnValue = methodInfo.Invoke(null, parameterValues);
}
catch (Exception ex)
{
Console.Write(ex.Message);
}

=====================================================================
C++ code follows
=====================================================================

extern "C"
{
__declspec( dllexport ) void WINAPI AddTwoDoubles(double a, double b)
{

CString str;
str.Format(_T("%lf + %lf = %lf"), a, b, a+b);
AfxMessageBox(str);
}
__declspec( dllexport ) double WINAPI AddTwoDoubles2(double a, double b)
{
return a+b;
}
}
 
W

Willy Denoyette [MVP]

Not sure where the stack imbalance comes from, but IMO you are missing:

methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
before you call:
| moduleBuilder.CreateGlobalFunctions();

Willy.



| Hi
| I'm trying to call a native C++ dll using the following code (both C# and
| C++ code segments included). When I make the call to the method
| (AddTwoDoubles) that has no return value all is fine. When I try and call
a
| function that returns a double (AddTwoDoubles2) I get the following
message:
|
|
| PInvokeStackImbalance was detected
| Message: A call to PInvoke function 'tempModule!<Module>::AddTwoDoubles2'
| 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 signature.
|
| I can't see what I'm doing wrong.
|
| Thanks for any help that anyone can provide.
|
| Marek
| =====================================================================
| C# code follows.
| =====================================================================
| //...Set up the return value:
| //Type returnType = null; //...Function (AddTwoDoubles) with void return
| works
| Type returnType = typeof(double); //...Function (AddTwoDoubles2) does not
| work
|
| //...Set up the parameters:
| Type[] parameterTypes = new Type[2];
| object[] parameterValues = new object[2];
|
| parameterTypes[0] = typeof(double);
| parameterValues[0] = 2.0;
| parameterTypes[1] = typeof(double);
| parameterValues[1] = 2.0;
|
| // Create a dynamic assembly and a dynamic module
| AssemblyName assemblyName = new AssemblyName();
| assemblyName.Name = "tempDll";
| AssemblyBuilder assemblyBuilder =
| AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
| AssemblyBuilderAccess.Run);
| ModuleBuilder moduleBuilder =
| assemblyBuilder.DefineDynamicModule("tempModule");
|
| // Dynamically construct a global PInvoke signature using the input
| information
| MethodBuilder methodBuilder =
| moduleBuilder.DefinePInvokeMethod(entryPointName, dllName,
| MethodAttributes.Static | MethodAttributes.Public |
| MethodAttributes.PinvokeImpl, CallingConventions.Standard, returnType,
| parameterTypes, CallingConvention.Winapi, CharSet.Ansi);
|
| moduleBuilder.CreateGlobalFunctions();
|
| // Get a MethodInfo for the PInvoke method
| MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);
|
| // Invoke the static method and return whatever it returns
| ParameterInfo[] parameterInfo = methodInfo.GetParameters();
|
| try
| {
| Object returnValue = methodInfo.Invoke(null, parameterValues);
| }
| catch (Exception ex)
| {
| Console.Write(ex.Message);
| }
|
| =====================================================================
| C++ code follows
| =====================================================================
|
| extern "C"
| {
| __declspec( dllexport ) void WINAPI AddTwoDoubles(double a, double b)
| {
|
| CString str;
| str.Format(_T("%lf + %lf = %lf"), a, b, a+b);
| AfxMessageBox(str);
| }
| __declspec( dllexport ) double WINAPI AddTwoDoubles2(double a, double b)
| {
| return a+b;
| }
| }
|
|
 
M

Marek

Hi Willy

That certainly did the trick. Thank you.

Have you any experience of what changes I need to make to the code to pass
arrays and return values (byref as opposed to byval) as well as the good old
passing and retrieval of string parameters?

Thanks again.

Marek

Willy Denoyette said:
Not sure where the stack imbalance comes from, but IMO you are missing:


methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
before you call:
| moduleBuilder.CreateGlobalFunctions();

Willy.



| Hi
| I'm trying to call a native C++ dll using the following code (both C#
and
| C++ code segments included). When I make the call to the method
| (AddTwoDoubles) that has no return value all is fine. When I try and
call
a
| function that returns a double (AddTwoDoubles2) I get the following
message:
|
|
| PInvokeStackImbalance was detected
| Message: A call to PInvoke function
'tempModule!<Module>::AddTwoDoubles2'
| 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 signature.
|
| I can't see what I'm doing wrong.
|
| Thanks for any help that anyone can provide.
|
| Marek
| =====================================================================
| C# code follows.
| =====================================================================
| //...Set up the return value:
| //Type returnType = null; //...Function (AddTwoDoubles) with void return
| works
| Type returnType = typeof(double); //...Function (AddTwoDoubles2) does
not
| work
|
| //...Set up the parameters:
| Type[] parameterTypes = new Type[2];
| object[] parameterValues = new object[2];
|
| parameterTypes[0] = typeof(double);
| parameterValues[0] = 2.0;
| parameterTypes[1] = typeof(double);
| parameterValues[1] = 2.0;
|
| // Create a dynamic assembly and a dynamic module
| AssemblyName assemblyName = new AssemblyName();
| assemblyName.Name = "tempDll";
| AssemblyBuilder assemblyBuilder =
| AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
| AssemblyBuilderAccess.Run);
| ModuleBuilder moduleBuilder =
| assemblyBuilder.DefineDynamicModule("tempModule");
|
| // Dynamically construct a global PInvoke signature using the input
| information
| MethodBuilder methodBuilder =
| moduleBuilder.DefinePInvokeMethod(entryPointName, dllName,
| MethodAttributes.Static | MethodAttributes.Public |
| MethodAttributes.PinvokeImpl, CallingConventions.Standard, returnType,
| parameterTypes, CallingConvention.Winapi, CharSet.Ansi);
|
| moduleBuilder.CreateGlobalFunctions();
|
| // Get a MethodInfo for the PInvoke method
| MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);
|
| // Invoke the static method and return whatever it returns
| ParameterInfo[] parameterInfo = methodInfo.GetParameters();
|
| try
| {
| Object returnValue = methodInfo.Invoke(null, parameterValues);
| }
| catch (Exception ex)
| {
| Console.Write(ex.Message);
| }
|
| =====================================================================
| C++ code follows
| =====================================================================
|
| extern "C"
| {
| __declspec( dllexport ) void WINAPI AddTwoDoubles(double a, double b)
| {
|
| CString str;
| str.Format(_T("%lf + %lf = %lf"), a, b, a+b);
| AfxMessageBox(str);
| }
| __declspec( dllexport ) double WINAPI AddTwoDoubles2(double a, double
b)
| {
| return a+b;
| }
| }
|
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top