Red Gate forums :: View topic - Pinvoke structs and functions
Return to www.red-gate.com RSS Feed Available

Search  | Usergroups |  Profile |  Messages |  Log in  Register 
Go to product documentation
PInvoke.Net
PInvoke.Net forum

Pinvoke structs and functions

Search in PInvoke.Net forum
Post new topic   Reply to topic
Jump to:  
Author Message
pyrek



Joined: 23 Aug 2010
Posts: 5

PostPosted: Mon Aug 23, 2010 3:31 pm    Post subject: Pinvoke structs and functions Reply with quote

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.
Back to top
View user's profile Send private message
pyrek



Joined: 23 Aug 2010
Posts: 5

PostPosted: Tue Aug 24, 2010 11:50 am    Post subject: Reply with quote

Hi again.
maby i will tell about my problrm in difrent way Smile
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.
Back to top
View user's profile Send private message
Chris128



Joined: 24 Aug 2010
Posts: 6

PostPosted: Tue Aug 24, 2010 11:40 pm    Post subject: Reply with quote

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 Smile
_________________
My blog: http://cjwdev.wordpress.com
Back to top
View user's profile Send private message
pyrek



Joined: 23 Aug 2010
Posts: 5

PostPosted: Wed Aug 25, 2010 2:49 pm    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message
Chris128



Joined: 24 Aug 2010
Posts: 6

PostPosted: Wed Aug 25, 2010 4:15 pm    Post subject: Reply with quote

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:
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 Smile
_________________
My blog: http://cjwdev.wordpress.com
Back to top
View user's profile Send private message
pyrek



Joined: 23 Aug 2010
Posts: 5

PostPosted: Wed Aug 25, 2010 10:04 pm    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message
pyrek



Joined: 23 Aug 2010
Posts: 5

PostPosted: Thu Sep 02, 2010 1:36 pm    Post subject: Reply with quote

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ł
Back to top
View user's profile Send private message
Spinkow



Joined: 21 Oct 2011
Posts: 1

PostPosted: Fri Oct 21, 2011 7:56 am    Post subject: Re: Reply with quote

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
Back to top
View user's profile Send private message
rigamonk



Joined: 30 Jun 2010
Posts: 2

PostPosted: Fri Dec 16, 2011 9:43 pm    Post subject: Reply with quote

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

try something like:
Code:
[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
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic All times are GMT + 1 Hour
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group