|
Hello,
I have a third party DLL that contains a create function, it creates an object in memory and returns a handle to it. When I am finished with it I can call a Destroy function with the handle to get rid of the object. While I am using the object each function the DLL has takes the handle to the object.
My question is: How do I write the DllImport stuff to get this handle properly?
I've tried:
[DllImport("tp.dll")]
internal static extern unsafe void* OpenFilter();
[DllImport("tp.dll")]
internal static extern unsafe void CloseFilter(void* handle);
[DllImport("tp.dll")]
internal static extern unsafe int IsOpen(void* handle);
and the same again with the void* replaced by IntPtr.
What am I doing wrong? If I write a test application in C I can use the DLL fine, but if I try the same in C# it doesn't work. Is there a problem with the way the third party DLL allocated its memory?
The third party DLL exposes C style functions and the same API as a C++ class (compatible with Visual C++ 6.0)
Any help would be much appreciated.
Cheers,
Andy.
|
|
|
|
|
Andy MacAngus wrote:
[DllImport("tp.dll")]internal static extern unsafe void* OpenFilter();[DllImport("tp.dll")]internal static extern unsafe void CloseFilter(void* handle);[DllImport("tp.dll")]internal static extern unsafe int IsOpen(void* handle);
Just a guess, but try:
[DllImport("tp.dll")]
public static extern IntPtr OpenFilter();
[DllImport("tp.dll")]
public static extern void CloseFilter(IntPtr handle);
[DllImport("tp.dll")]
public static extern int IsOpen(IntPtr handle);
- Nick Parker My Blog
|
|
|
|
|
You never mentioned what the problem is. Since you're using C-style declarations, that clears-up one problem. Is this native DLL in a resolvable directory (i.e., current working directory or something in the %PATH%)? Are any exceptions thrown, and - if so - what exception (i.e., Type and text)?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for answering.
Yes, this is a native DLL - I believe it was written with Visual C/C++ 6.0 (the C++ part of it only works when linked with VC++6)
The DLL is in the same directory as the C# exe.
No exceptions are thrown. I think that the pointer that I am receiving back is not right but I don't know how to tell or not. If a native DLL allocates memory when being used in a managed application is there anything special I need to do? I've written a test application in C as well as the C# version and the test works in C - the code is virtually identical.
The symptom of the error is that when running in C# the IsOpen() function always returns false.
|
|
|
|
|
Andy MacAngus wrote:
If a native DLL allocates memory when being used in a managed application is there anything special I need to do?
It depends. Is the caller expected to free the memory? If so, you should use GlobalAlloc or CoTaskMem , which you can free with the Marshal class methods.
What is this a pointer to? If it's a pointer to a struct, for instance, you need to define that struct in managed code and you can use Marshal.PtrToStructure . Keep in mind your managed-unmanaged marshaling, too, which you can control with MarshalAsAttribute and knowledge of bit-lengths (like an int in unmanaged code should use UnmanagedType.SysInt since its bit-length is system-dependent, and a LONG and INT in unmanaged code are both an Int32 in managed code.
Note, from what I can tell, you don't need any unsafe code here. IntPtr will usually do what you need it to.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi,
The caller is not expected to do anything to allocate or deallocate memory. The OpenFilter() and CloseFilter() functions do that. They return a HANDLE (which is just a C-macro definition for void*) so it is a pointer to something I don't know much about it is all accessed through the API that the DLL exposes.
I tried using the IntPrr but I just get the same results. What is most fustrating is that I can see it working in C (all I am doing in my test is an open, test for is open then close)
Cheers,
Andy
|
|
|
|
|
Andy MacAngus wrote:
They return a HANDLE (which is just a C-macro definition for void*)
Thanks, I know! I started programming on C many, many years ago. Still use it sometimes.
What you're doing isn't at all different from what MANY classes in the .NET base class library, do. Take controls in Windows Forms, for example - they all use window handles (HWND s), as well as many other types of handles (all typedefs of the same thing, of course).
You mentioned that you're checking the return of IsOpen against a boolean expression. Are you comparing against true or false ? Or are you equating the return against 0, 1, some negative number, etc? In the former case, you should declare your method return value as a bool , so long as the concept of a boolean in your unmanaged code uses 0 for false and anything else for true (like the BOOL typedef). You'd probably get compiler errors otherwise, but I honestly can't see the problem.
You're right to use an IntPtr for void* . Despite your return value, do you get a valid memory address? If you share these two projects in a simple solution (you'll have to upgrade the old VC++ 6 project, of course), you could actually debug projects and see what is happening in both managed and unmanaged code.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath Stewart wrote:
so long as the concept of a boolean in your unmanaged code uses 0 for false and anything else for true
Yes, that's what I'm doing:
if (IsOpen(_handle) == 0)
{
Console.WriteLine("Not Open");
return;
}
else
{
Console.WriteLine("Open");
}
Heath Stewart wrote:
you could actually debug projects and see what is happening in both managed and unmanaged code.
That's what I'm going to do. Thanks for your help. This is probably a little bit more complex than I had hoped.
|
|
|
|
|
It's not complex, just odd. Like I said, the base class library uses handles for much of the functionality, from drawing to controls to image lists to file streams and more. I use this type of approach a lot myself. Anything dealing with ActiveX controls uses a lot of handles. Overriding functionality of an existing control almost always requires working with handles and passing them to unmanaged functions. In these cases, you merely use IntPtr for handles.
The only other thing that I can think of is that you could try using ref IntPtr p as your parameter (or replace ref with out ). This usually isn't required, though. So your calls would look like:
IntPtr ptr;
OpenFilter(out ptr);
if (IsOpen(ptr) == 0) CloseFilter(ptr); OpenFilter would have to be declared with ref or out as well. ref requires an instantiated input and is typically used for [in, out] declarations, where out does not require an instance is is typically used for [out] declarations.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
hi,
i want to get the window coordinates
|
|
|
|
|
Of what? Your form? You can use Form.PointToScreen(this.Bounds) to get a Point in scren coordinates, where this is your Form class. PointToScreen is actually a static method inheritted from Control .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
i dont want to get the form coordinates but i have the handle of specific window and i want to get its coordinates i knew the Fn. but i dont know how to use it in C# the Function is bool GetWindowRect(HWnd,LpRect)
i donot know how use the pointer.
|
|
|
|
|
P/Invoke the API:
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT rc); You must also define the RECT structure, since System.Drawing.Rectangle doesn't have the same meaning for its fields:
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
} Then, just pass the handle of the Window in which you're interested to get back the RECT :
RECT rc;
GetWindowRect(hWnd, out rc); Now you've got your coordinates.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am currently trying to implement some functionality that was originally done in vb6. I want to do something similar to the getObject method. I need to find an assembly that is currently in memory, and make function calls to that assembly. So my question is two fold, when creating an assembly to run, do I need to create registry entries to "publish" that running assembly that will be used by other assemblies. Secondly, what method should I use to search for that running assembly, connect to it, and use its functions. I should of mentioned this earlier, it needs to be done through COM because the assembly will be called from an unmanaged c++ assembly.
Thanks for the help everyone,
Ryan
|
|
|
|
|
Sounds like you're talking about the Running Object Table (ROT). .NET provides a way to get an object publishes in the ROT using Marshal.GetActiveObject (using a ProgID). This, of course, is not what you want.
In order to accomplish this, you need to P/Invoke the RegisterActiveObject and RevokeActiveObject APIs and properly expose your .NET component as a CCW. This means that you must use regasm.exe (or your own implementation that registers the type) either using the /codebase option to register the full path to the assembly, or without if your assembly is in the GAC. Use /tlb to create and register the typelib. With that typelib, you can easily call late-bound methods on the COM object after getting it from the ROT.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
|
Hello all!
I am a VB developer and I used API Viewer.
I would like to know if Visual Studio .NET 2003 have a similar tool ?
Thanks for all,
Alexsander "Axia" Antunes
|
|
|
|
|
The API Viewer just displayed some of the Win32 functions in VB form once it was supplied a text file. So far, no tools have been written that do something similar for any .NET languages (to my knowledge). Some Microsoft employees have discussed this idea (via their blogs) of creating a tool, however it has been deemed too time consuming. If you are using C# (I am assuming this since you are in the C# forum) you will need to P/Invoke the Win32 method signatures to call them from C#, VB.NET or any .NET language in particular. Read into the DllImportAttribute Class[^] for more information.
- Nick Parker My Blog
|
|
|
|
|
I'm trying to protect one of my classes using PrincipalPermissionAttribute. I'm setting it to only allow the code to execute only if a specific user is trying to run it.
Here is the class declaration:
[PrincipalPermissionAttribute(SecurityAction.Demand, Authenticated:=True, name:="MYDOMAIN\\Mauricio")] public class foo
This code works fine but the problem is that it allows the usage of an GenericPrincipal object and I want it to use a WindowsPrincipal object. Allow it to use a GenericPrincipal will anyone to create a GenericPrincipal with that user name and execute the code. Like this:
GenericIdentity oIdent = new GenericIdentity("MYDOMAIN\\Mauricio", "NTLM");
GenericPrincipal oPrinc = new GenericPrincipal(oPrinc, null);
foo oFoo = new foo();
My question is: is there anyone to demand that a code only accepts WindowsPrincipals, and don't accept GenericPrincipals ?
thanks
Mauricio Ritter - Brazil
Sonorking now: 100.13560 MRitter
English is not my native language so, if you find any spelling erros in my posts, please let me know.
|
|
|
|
|
The only way you'll be able to do this is to extend the PrincipalPermission and PrincipalPermissionAttribute classes, or create your own. You could do the very same things, except check the Type against WindowsPrincipal that you get back from Thread.CurrentPrincipal . The current implementation doesn't care about the Type, so long as it implements IPrincipal .
If you want to know exactly what the current classes mentioned above are doing, you can use ildasm.exe that ships with the .NET Framework SDK if you know IL (and it wouldn't hurt to know anyway), or use a good decompiler like .NET Reflector[^].
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I have 2 panels, one docked to the left and the other docked to the bottom. I hide the left panel on startup but during runtime when i show it, i "pushed" the bottom panel to make room for itself. How can i prevent this. i.e. The left panel should be above the bottom panel.
<font=arial>Weiye Chen
When pursuing your dreams, don't forget to enjoy your life...
|
|
|
|
|
It's all about the order in which controls are added. Controls that are added first take precedence when docking over controls that are added later. When using Control/ControlCollection.AddRange , you need to add these in reverse order. How exactly are you "hiding" this control?
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes, i am adding them in the reverse order.
this.Controls.AddRange(new System.Windows.Forms.Control[] { this.panelLeft, this.panelBottom, ...});
Heath Stewart wrote:
How exactly are you "hiding" this control?
In the designer, both panels' Visible flags are set to false. In my application, there are 2 toggle buttons each calling the Hide() and Show() methods of the panels.
<font=arial>Weiye Chen
When pursuing your dreams, don't forget to enjoy your life...
|
|
|
|
|
I'm not sure if this will work, but try re-creating the handle for each control after changing the visibility of one (perhaps override OnVisibleChanged and doing it from within there after the call to base.OnVisibleChanged ). Since it appears that the control is re-created when changing the visibility of the current control, you could always handle the VisibleChanged event of the other control and re-create your own handle as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I just got it to work by inserting another control between the 2 panels during AddRange(...)
this.Controls.AddRange(new System.Windows.Forms.Control[] { this.panelLeft, this.progressBar, this.panelBottom, ...});
But this doesn't make sense. The progress bar is located far away from the panels. Ah, never mind.... Thanks anyway...
<font=arial>Weiye Chen
When pursuing your dreams, don't forget to enjoy your life...
|
|
|
|
|