|
Hey, Nish...
When working with COM interop, be sure to check out the System.Runtime.InteropServices.Marshal class. It can be very helpful.
For example, there is a Marshal.FreeBSTR method. All this does is call SysFreeBSTR for you, but saves you from having to P/Invoke it yourself which saves you from requiring an extra code access permission or two (unless you P/Invoke'd other APIs). The trick is that Marshal.FreeBSTR requires an IntPtr - the address to the BSTR . You can get the address like so:
private void FreeBSTR(string bstr)
{
GCHandle handle = GCHandle.Alloc(bstr);
try
{
Marshal.FreeBSTR(handle.AddrOfPinnedObject());
}
finally
{
if (handle.IsAllocated) handle.Free();
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hey Heath,
Thanks for the reply.
So are you saying that, the string object that the RCW layer returns to the C# client will still internally refer the BSTR memory?
I'd have thought that the original BSTR returned from the COM method is ignored once its contents are used to construct a new string object.
Heath, are there any MSDN links or articles that explain how RCW internally works?
Thanks once again for some really interesting info
Nish
Now with my own blog - void Nish(char* szBlog);
My MVP tips, tricks and essays web site - www.voidnish.com
|
|
|
|
|
Internally, no. The best you could do is search Microsoftie blogs and see what you can find. In the .NET Framework SDK and other articles I've seen on MSDN, it's mostly higher level stuff.
Instead of having your method return a marshaled string have it return an IntPtr (may require hand-coding the RCW) and use Marshal.PtrToStringBSTR . After calling it, use Marshal.FreeBSTR with the IntPtr return value since Marshal.PtrToStringBSTR creates a copy, which implies you are indeed right. Guess I didn't consider that, though it does make complete sense. Maybe I should've slept in longer on this Saturday morning.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks a heap, Heath
I was writing a blog entry for my blog on this RCW issue of returning a BSTR and was just wondering if perhaps RCW internally solves this issue. So I didn't want to write something without first confirming that the issue does exist.
I'll remember to thank you in my blog entry
Heath Stewart wrote:
Maybe I should've slept in longer on this Saturday morning.
Sleep does you a world of good Get as much of it as possible as you'll probably get busier in the near future as you land up lucrative sub-contracts and stuff.
Nish
Now with my own blog - void Nish(char* szBlog);
My MVP tips, tricks and essays web site - www.voidnish.com
|
|
|
|
|
Nishant S wrote:
...as you land up lucrative sub-contracts and stuff.
Man, I wish...
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
i took two listbox web server controls..ok
In My Listbox1 there is some data which comes from database
on client side i added some elements from listbox1 to listbox2 i have done this by using javascript ok...
Now on some event my page is going to refresh.. so what ever the data i have add on client side in listbox2 vanishes as page get refresh..
what i think as .Net provide a view state so how it get vanishes ....
so can u tell me where i m wrong...
the reason behind to think so, is that (if we add some data in text box through javascript or we just enter through our key board) and when it do the server trip it remains there ,then why not for list box.. so please help me and tell me where i m wrong...
thanks in advance...
|
|
|
|
|
|
Hai all...
I was trying to pass a class to an Unmanaged function. The class has a member of type, of the same class. Is it possible to pass a Managed class(Class having a member of it's own type) to an Unmanaged function.
Thanks in advance
Below is what i did...
This is the class i created to pass into an Unmanaged function as parameter
[StructLayout(LayoutKind.Explicit )]
public class MyWindow
{
[FieldOffset (0)]
public String className;
[FieldOffset (16)]
public String caption;
[FieldOffset (32)]
public MyWindow child ;
}
But if i remove the class member 'child' from the class it works well.
Unmanaged function Decleration
[DllImport("user32")]
public static extern bool EnumChildWindows(int hwndParent, EnumChildDelegare lpEnumFunc, MyWindow lParam) ;
This is the way how i call the unmanaged function
MyWindow m = new MyWindow ();
Win32Calls.EnumChildWindows (winHandle,w.enumChildDlgate ,m);
And i am getting this error.
An unhandled exception of type 'System.TypeLoadException' occurred in CSRecorder.exe
Additional information: Can not marshal field child of type CSRecorder.MyWindow: This type can not be marshaled as a structure field.
Shaju Mathew
|
|
|
|
|
First, change the class to a struct. This allocates the data on the stack so it will not be moved. While this isn't the direct cause of your problem, it may lead to them. If it's a class - which is allocated on the heap - the GC (Garbage Collector) may move it when necessary and your handle that your enumerator is using would be invalid. Declaring this as a struct should also fix the other error.
There is a problem with your EnumChildWindows as well. An HWND is a processor-dependent type. You should really declare this as IntPtr , which works well since P/Invoking other unmanaged Windows APIs will use IntPtr and Control.Handle (the HWND for the control) is also of type IntPtr . Any native int or unsigned int should be declared as an IntPtr .
Also, for your struct, just use LayoutKind.Sequential . You really don't even need that, however, since the memory address to your struct's instance is being passed to your enumerator so it doesn't need to be marshaled for use with unmanaged code. Just a couple of tips.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks... Heath Stewart
The tips helped ..
But i cannot change class to struct. Since struct won't allow the same struct as a member
Shaju Mathew
|
|
|
|
|
In that case, use a GCHandle to pin the class instance in memory. The GC (Garbage Collector) may relocate the object in memory, so the address would change. Unmanaged code can't deal with those changes so you'll get all sorts of errors since your object isn't where it's supposed to be.
You can find more information about the GCHandle class in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
When I was marshalling EnumChildWindows, I declared the function like that:
[DllImport("user32.dll",SetLastError=true)]<br />
public static extern bool EnumChildWindows( <br />
IntPtr hWndParent,<br />
User32Functions.EnumWindowsCallback lpEnumFunc,<br />
IntPtr lParam<br />
);
The point is, why do you need to pass a class or struct as the third parameter?
I followed the MSDN recommendation and called the function like that:
GCHandle gch=GCHandle.Alloc(this.twHandles);<br />
User32.EnumChildWindows(handleParent,this.enumThreadCallback,(IntPtr)gch);<br />
gch.Free();
Here this.twHandles is a text writer, which i later (in the callback function) use like so:
private bool CaptureEnumThreadWindows(int handle, IntPtr param)<br />
{<br />
GCHandle gch=(GCHandle)param;<br />
TextWriter tw=(TextWriter)gch.Target;<br />
twHandles.Write(handle.ToString()+" ");<br />
twHandles.Flush();<br />
return true;<br />
}
Anyway, MSDN recommends to use GCHandle , 'so the delegate does not get moved by GC before the call ends, however I was trying to use without GCHandle, just passing IntPtr.Zero as the last parameter and it works anyway. Frankly I don't understand how this (GCHandle) can prevent the delegate from being moved by GC, but that's what MSDN says. (see GCHandle sample)
|
|
|
|
|
Thanks Ael
GCHandle worked well And it solved my problem.
Shaju Mathew
|
|
|
|
|
Hy.
My problem is that I'm new in this field (DirectShow filter) and I need to use a particular filter in my app.
I think is possible but I really don't know how.
So , I have a DirectShow filter with the AX extension (executable , I think)
written in C++ and I want to use it in my C# app.
Can anyone help me ?
Thanks.
Angel
|
|
|
|
|
If you're working with DirectX in C#, I recommend you take a look at the Managed DirectX 9.0 extensions - written from ground-up for .NET - at http://msdn.microsoft.com/directx[^]. You can also download the Summer 2003 Update (the full thing - just the latest SDK and runtime) from there.
Unfortunately, Managed DirectX does not contain a managed assembly or classes for DirectShow (at least not yet; I'm really not sure of future plans). If it was, you'd be able to register your filter's COM server and use the CLSID like you can with other managed classes in Managed DirectX 9.0.
There are several ways you can use your filter, though. One would be to write a native C/C++ library (DLL) that instantiates your filter's COM object and streams data through it. You could export certain functions that do this and use P/Invoke in C# to execute those exported functions (see the DllImportAttribute class documentation in the .NET Framework SDK).
Another way would be to write a mixed-mode Managed C++ assembly that can use native functions and wrap them in a managed class. You can then use this assembly in your C# project. Thanks to the Common Language Infruastructure (the CLI), languages can interoperate with each other because they compile to a Common Intermediate Language, or CIL.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks for answering.
What you are saying surely is interesting but I'm kind of on a time schedule with this app.
I found NetMaster's DShowNET on this site and is working just fine in C#.
My problem is that the video I receive comes from a network , so the first filter in my graph should be one that can extract data from a net. I think I have the filter but when I try to use DShowNET's EnumFilters NEXT function I receive an error about the IBaseFilter variable.The code compiles ok , the error comes at runtime.
****************
IBaseFilter[] pf;
IEnumFilters pe=null;
int fetch;
int hx,cod;
hx=gr.EnumFilters(out pe); // hx=0 after this
cod=pe.Next(1,out pf, out fetch); // Error : "Can not use SizeParamIndex for byref array parameters.
// gr is the graph.I've tested it and it works
*****************
Normaly , it shoud be possible to get graph filter's info , add and replace filters in C# using DShowNET.dll , but I can't get pass this error.
Any ideeas ?
Thanks in advance.
Angel
|
|
|
|
|
I'm not familiar with that project. If yo uhave questions specific to that project, you should redirect them to the message board at the bottom of that article.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Try replacing the current IEnumFilters Next COM signature with:
int Next([In] int cFilters, out IBaseFilter pFilter, [Out] out int filtersFetched);
Example client code would be:
FilterInfo fi = new FilterInfo();
while(0 == enumFilters.Next(filtersToFetch, out filter, out filtersFetched))
{
filter.QueryFilterInfo(fi);
}
|
|
|
|
|
Hello,
I am new to this forum but I am most definitely not new to programming. I have been coding in C++ console for allmost 3 years and C++ console structures, pointers, trees, etc. for over a year. After completing a college course in VB.net I have found that C# is the ultimate in GUI programming. Integrating my console C++ programs into C# has been a breeze! I would say if you know C++ console very well and VB.net and with a couple of C# books you can become expert in no time. I have been developing a program in C++ console for the past year and I have only recently migrated to C# last month in April. C# has probably cut an least year off of my development time. I fully expect a release date on or around Sept.8,2004. If anyone reading this thread would like to follow my C# progress please check the following link...
http://www.demasoni.com
I would recommend C# for GUI C++ programming.
jjsjr
|
|
|
|
|
Thanks very much for the advertisement...
|
|
|
|
|
NO problem David, I rarely talk about the quality of a product but C# is a very nice development enviroment and my current software project is proof of it.
BTW: This site has some of the best examples on the web for C#. It has helped me with my current project. I will use it again from time to time.
js
|
|
|
|
|
how to config a serial number in InstallShield.
Thank in advance.
QuocBao
|
|
|
|
|
The InstallShield documentation explains this and gives examples if you look. This has nothing to do with C#.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm writing an MP3 player, with queueing capabilities - it writes the queue to a temporary text file, and I also have another form in the app that allows me to view the queue. This works fine, but I can't refresh the queue automatically. I would like to be able to just call the writeQ function in the main form to write the queue, then call the queue viewer forms' load function which would read the necessary data. But, my problem is, I don't understand how I can get the handle of the main form to call the writeQ. simply doing a MainPlayer mainP = new MainPlayer() then calling mainP.writeQ() (MainPlayer is the main form class) won't work, because it'll try to read the listBox in the queue viewer form...Anyone know how I could force it to read the listBox in its own form? I would think I can do it using IntPtr and window handles, but I have no idea quite how to do this.
|
|
|
|
|
The thing you want to do, i think is done more easily in that way.
Once the user want to change your playlist immediately you go and update the file you are writing. The other form will use a filesystemwatcher component so that once it sees that the file you want changed he will go and update the view of the playlist. If you want to do the thing you are saying you will have to mark the writeQ method as public and when you create the viewer form pass a variable of type MainPlayer with the mainform in it in the constructor and store this variable as a member and call the function writeQ in it.
From Greece:
Dimitris Iliopoulos
dimilio@yahoo.com
|
|
|
|