Pinvoke structs and functions

Announcements and discussion for PInvoke

Moderators: Luke Jefferson, Robert

Pinvoke structs and functions

Postby pyrek » Mon Aug 23, 2010 3:31 pm

Hi all.
I'm working on some project using firmwere SDK which is specyfised for C++ code, unforunetly my project need to be written in C#.
I have big problem now.
I've tried to invoke isngle method like:

[DllImport(FGLLIBNAME_C)]
private static extern IntPtr Fg_Init(String Filename, uint BoardIndex);
where FGLLIBNAME_C is name of dll used by me - "fglib5.dll"

when i try to use Fg_Init method i have fail

"A call to PInvoke function 'SisoSDKExample1!Siso.SisoSDK::Fg_Init' 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."

In C++ that function is used like that:
fg=Fg_Init(...) where fg is a pointer to some struct. Now i have a question.
Do i have to invoke also a FG_STRUCT from fglib5.dll or maby i need to declare my own struct simillar to orginal one. If i need to invoke one, how i need to do that.
Thanks for all help and sorry for my english.
pyrek
 
Posts: 5
Joined: Mon Aug 23, 2010 3:22 pm

Postby pyrek » Tue Aug 24, 2010 11:50 am

Hi again.
maby i will tell about my problrm in difrent way :)
Im writing project using some api. I can invoke all methods without compilation errors, but a huge amount of them are used with a pointer to some struct called FG_Struct.
To example:
in C:

FG_Struct *fg;
fg = FG_init(...);

That code is used to initialize framegrabber made by silicon software.
I want it in C#;
I've done like this:

public IntPtr pFGHandle;
const String FGLLIBNAME_C = "fglib5.dll";
[DllImport(FGLLIBNAME_C)]
private static extern IntPtr Fg_Init(String Filename, uint BoardIndex);

public int FGInit(String HapName, uint BoardNo)
{
int rc;

pFGHandle = Fg_Init(HapName, BoardNo);

rc = pFGHandle.ToInt32();
return rc;
}

in compilation this is ok, but when i want to call FGInit method, there is an error i say before. What schoult i do?
THis is very important to me couse is a part of my diplom project couse i've graduated technical university.
pyrek
 
Posts: 5
Joined: Mon Aug 23, 2010 3:22 pm

Postby Chris128 » Tue Aug 24, 2010 11:40 pm

Can you post the C++ typedef for the method? If the function definitely just returns a pointer then you should not get that error that you are getting. It is likely due to one of the arguments - probably the String argument. If you can post the C++ signature for the function then we can tell you how you should marshal the arguments in .NET :)
Chris128
 
Posts: 6
Joined: Tue Aug 24, 2010 9:37 am

Postby pyrek » Wed Aug 25, 2010 2:49 pm

Hi, and thanks for interesting in my case:
Here is all i can find in SDK to my device:


Fg_Struct * Fg_Init (const char *FileName, unsigned int BoardIndex)
The function Fg_Init() initializes the frame grabber.
The function Fg_Init() initializes the frame grabber.


This functions is equivalent to calling Fg_InitEx(FileName, BoardIndex, 0). Please see the documentation of Fg_InitEx() for a detailed description of the parameters.

An initialized frame grabber resource by Fg_Init() must be released by Fg_FreeGrabber().
Parameters: FileName Applet name for initialization.
BoardIndex Logical number of the board.

Returns:
Initialized pointer on the data structure of the FrameFrabber.
Return values: NULL The initialization failed.


If this function returns NULL you may call Fg_getLastErrorNumber(NULL) to get the error code.

SDK manual says that it returns pointer to struct, here is some about struct:

Fg_Struct


The structure for a framegrabber.

This struct is used as a handle to the currently opened board and design.


now something from code:

/**
* \\brief The function Fg_Init() initializes the frame grabber.
*
* This functions is equivalent to calling Fg_InitEx(FileName, BoardIndex, 0). Please see the
* documentation of Fg_InitEx() for a detailed description of the parameters.
*
* An initialized frame grabber resource by Fg_Init() must be released by Fg_FreeGrabber().
*
* \\param FileName Applet name for initialization.
* \\param BoardIndex Logical number of the board.
*
* \\returns Initialized pointer on the data structure of the FrameFrabber.
* \\retval NULL The initialization failed.
*
* If this function returns NULL you may call Fg_getLastErrorNumber(NULL) to get the error code.
*/
Fg_Struct *Fg_Init(const char *FileName, unsigned int BoardIndex);

and this is using of that function in cpp code:

// Initialization of the microEnable frame grabber
if((fg = Fg_Init(dllName,nBoard)) == NULL) {
status = ErrorMessageWait(fg);
return status;
}
fprintf(stdout,"Init Grabber ok\\n");
where:
dllName = selectDll(boardType, dll_list_me3, dll_list_me3xxl, dll_list_me4_dual, dll_list_me4_single);

I know its a lot, but if u can, i would be very grateful for any help.
pyrek
 
Posts: 5
Joined: Mon Aug 23, 2010 3:22 pm

Postby Chris128 » Wed Aug 25, 2010 4:15 pm

Right well it looks like the function is expecting a pointer to a string, which should already be what is happening when you pass a String in because a String in .NET is a reference type, but perhaps try passing the string in by reference anyway just to see what happens. I'm more of a VB.NET person than C#.NET but I believe the way you would do it is like this:

Code: Select all
pFGHandle = Fg_Init(ref HapName, BoardNo)


If that doesn't work then you could try declaring that first argument as an IntPtr - then when you want to call the method you declare a String variable and populate it with whatever string you want, then use theMarshal.StringToHGlobalAnsi method to get a pointer to that string and pass that pointer (IntPtr) in to the method.

There may be something I'm missing and hopefully someone else can point out the solution if that is the case - I've not had to marshal a "const char *" before :)
Chris128
 
Posts: 6
Joined: Tue Aug 24, 2010 9:37 am

Postby pyrek » Wed Aug 25, 2010 10:04 pm

Hi, thanks for help, but unfortunetly both methods fails:(
Maby someone have another idea, how to marshal that method?

edit:

Hi again!
Today i've spoken with my profesor and we thought about writing neww dll in c++ using methods from fglib5 like i've tried in C# but changing some urguments to difrent types to make them easier to marshal.
To example we do not know how to marschal *char, but it could be changet to string, which is easy to do. What do You think about that?
If it is good idea, how to get methods from dll in c++, also using PInvoke?
Thanks for any help.
pyrek
 
Posts: 5
Joined: Mon Aug 23, 2010 3:22 pm

Postby pyrek » Thu Sep 02, 2010 1:36 pm

Hi,
Ive done dll with new methods, but it is the problem with load them, no matter.
Now i know i have poblem with returned by method fg_init type.
Producer seai that IntPtr will be ok, but it realy don't. How i can marsha special types as, fg_struct* which is a pointer to a struct. Do I need to tepedef all struct in menaged code? or can i do this in a diffrent way?
Pls Help if you can.
Paweł
pyrek
 
Posts: 5
Joined: Mon Aug 23, 2010 3:22 pm

Re:

Postby Spinkow » Fri Oct 21, 2011 7:56 am

Chris128 wrote:
If that doesn't work then you could try declaring that first argument as an IntPtr - then when you want to call the method you declare a String variable and populate it with whatever string you want, then use theMarshal.StringToHGlobalAnsi method to get a pointer to that string and pass that pointer (IntPtr) in to the method.

I have also seen some code on Stan Lippman's blog, but it's from 2004. I have also seen Marshal::StringToHGlobalAnsi(). Is there a method that is considered "best practice"?
Last edited by Spinkow on Thu Jun 21, 2012 2:00 pm, edited 2 times in total.
Spinkow
 
Posts: 1
Joined: Fri Oct 21, 2011 7:48 am

Postby rigamonk » Fri Dec 16, 2011 9:43 pm

The unbalanced stack may be caused by a mismatched calling convention. C functions use __cdecl....different cleanup method.

try something like:
Code: Select all
[DllImport("FGLLIBNAME_C", CallingConvention = CallingConvention.Cdecl)]

usually, unbalanced stacks are an indication of this problem, since it means that no one (called nor caller) has done the correct epilogue and the return pointer can't be found
rigamonk
 
Posts: 2
Joined: Wed Jun 30, 2010 5:26 pm


Return to PInvoke.Net

Who is online

Users browsing this forum: No registered users and 0 guests