I have a C# Winforms application that makes a call to a COM class. When debugging using Visual Studio it steps into the c++ code and returns S_OK but when the function returns visual studio hangs and the application crashes. I have to end process on the VS process to stop the program from running. If i run the app outside of visual studio the application simply crashes.
Everything was working fine and i have no idea what i may have done to cause this problem.
Any help is appreciated. Thanks
Sj
This is the interface definition
typedef struct
{
long ExpiryData
BSTR IssuedBy;
} LicenceData;
[
object,
uuid (5A734F95-EABE-440B-8B7E-0F73538A24AC),
pointer_default(unique),
helpstring("ILicenceReader Interface"),
]
interface ILicenceReader : IDispatch
{
HRESULT ReadLicenceFile ([in, out]LicenceData* plicenceData, LPCTSTR filePath);
};
[
uuid(C2833A21-6586-4648-ABC8-D42BC3225699)
]
coclass LicenceReader
{
[default] interface ILicenceReader;
};
I have referenced the COM dll and allowed VS to generate the Interop and the usage in the c# application:
LicenceData data = new LicenceData();
ILicenceReader reader = new LicenceReader();
reader.ReadLicenceFile(ref data, filePath);
Thanks for your help.
I'll bet that the COM subsystem is trying to unmarshall a BSTR allocated on the stack, or perhaps allocated with a smart pointer on the stack.
BSTRs have to be allocated with SysAllocString. The result from this can be returned as-is as it's not on the stack and nothing will try to free it erroneously.
If you use a smart pointer BSTR class such as CComBSTR or _bstr_t then you'll need to set the IssuedBy member via a Detach. CComBSTR::Detach() will return the pointer to the BSTR and not try to free it when that local instance of CComBSTR goes out of scope.
plicenceData->IssuedBy = CComBSTR("Some Dude").Detach();
Another possibility is that you try to do something like plicenceData = new plicenceData within your COM class, overwriting the instance passed in. That won't work.
In the end, pretty much the only reason a COM function fails after it's finished and returned is because of marshalling issues. It's the layer between your C# code and the called C++ that's trying to translate the data across apartment and possibly process boundaries. You need to ensure that you follow the COM rules to the letter to allow marshalling to do it's job.
So, double check all your pointers. Are they on the stack or on the heap? They need to be on the heap. Are all BSTRs allocated appropriately? Using smart BSTR classes will usually help significantly, but just remember that you can't return the raw members. Use these classes as they're expected to be used.
Related
I have an unmanaged library which has a function like this:
type* foo();
foo basically allocates an instance of the unmanaged type on the managed heap through Marshal.AllocHGlobal.
I have a managed version of type. It's not blittable but I have MarshalAs attributes set on members so I can use Marshal.PtrToStructure to get a managed version of it. But having to wrap calls to foo with extra bookkeeping to call Marshal.PtrToStructure is a bit annoying.
I'd like to be able to do something like this on the C# side:
[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStruct)]
type* foo();
and have C#'s marshaller handle the conversion behind the scenes, like it does for function arguments. I thought I should be able to do this because type is allocated on the managed heap. But maybe I can't? Is there any way to have C#'s inbuilt marshaller handle the unmanaged-to-managed transition on the return type for me without having to manually call Marshal.PtrToStructure?
A custom marshaler works fine if, on the .NET side, typeis declared as a class, not as a struct.
This is clearly stated in UnmanagedType enumeration:
Specifies the custom marshaler class when used with the
MarshalAsAttribute.MarshalType or MarshalAsAttribute.MarshalTypeRef
field. The MarshalAsAttribute.MarshalCookie field can be used to pass
additional information to the custom marshaler. You can use this
member on any reference type.
Here is some sample code that should work fine
[[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]
[return : MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef= typeof(typeMarshaler))]
private static extern type Foo();
private class typeMarshaler : ICustomMarshaler
{
public static readonly typeMarshaler Instance = new typeMarshaler();
public static ICustomMarshaler GetInstance(string cookie) => Instance;
public int GetNativeDataSize() => -1;
public object MarshalNativeToManaged(IntPtr nativeData) => Marshal.PtrToStructure<type>(nativeData);
// in this sample I suppose the native side uses GlobalAlloc (or LocalAlloc)
// but you can use any allocation library provided you use the same on both sides
public void CleanUpNativeData(IntPtr nativeData) => Marshal.FreeHGlobal(nativeData);
public IntPtr MarshalManagedToNative(object managedObj) => throw new NotImplementedException();
public void CleanUpManagedData(object managedObj) => throw new NotImplementedException();
}
[StructLayout(LayoutKind.Sequential)]
class type
{
/* declare fields */
};
Of course, changing unmanaged struct declarations into classes can have deep implications (that may not always raise compile-time errors), especially if you have a lot of existing code.
Another solution is to use Roslyn to parse your code, extract all Foo-like methods and generate one additional .NET method for each. I would do this.
type* foo()
This is very awkward function signature, hard to use correctly in a C or C++ program and that never gets better when you pinvoke. Memory management is the biggest problem, you want to work with the programmer that wrote this code to make it better.
Your preferred signature should resemble int foo(type* arg, size_t size). In other words, the caller supplies the memory and the native function fills it in. The size argument is required to avoid memory corruption, necessary when the version of type changes and gets larger. Often included as a field of type. The int return value is useful to return an error code so you can fail gracefully. Beyond making it safe, it is also much more efficient since no memory allocation is required at all. You can simply pass a local variable.
... allocates an instance of the unmanaged type on the managed heap through Marshal.AllocHGlobal
No, this is where memory management assumptions get very dangerous. Never the managed heap, native code has no decent way to call into the CLR. And you cannot assume that it used the equivalent of Marshal.AllocHGlobal(). The native code typically uses malloc() to allocate the storage, which heap is used to allocate from is an implementation detail of the CRT it links. Only that CRT's free() function is guaranteed to release it reliably. You cannot call free() yourself. Skip to the bottom to see why AllocHGlobal() appeared to be correct.
There are function signatures that forces the pinvoke marshaller to release the memory, it does so by calling Marshal.FreeCoTaskMem(). Note that this is not equivalent to Marshal.AllocHGlobal(), it uses a different heap. It assumes that the native code was written to support interop well and used CoTaskMemAlloc(), it uses the heap that is dedicated to COM interop.
It's not blittable but I have MarshalAs attributes set...
That is the gritty detail that explains why you have to make it awkward. The pinvoke marshaller does not want to solve this problem since it has to marshal a copy and there is too much risk automatically releasing the storage for the object and its members. Using [MarshalAs] is unnecessary and does not make the code better, simply change the return type to IntPtr. Ready to pass to Marshal.PtrToStructure() and whatever memory release function you need.
I have to talk about the reason that Marshal.AllocHGlobal() appeared to be correct. It did not used to be, but has changed in recent Windows and VS versions. There was a big design change in Win8 and VS2012. The OS no longer creates separate heaps that Marshal.AllocHGlobal and Marshal.AllocCoTaskMem allocate from. It is now a single heap, the default process heap (GetProcessHeap() returns it). And there was a corresponding change in the CRT included with VS2012, it now also uses GetProcessHeap() instead of creating its own heap with HeapCreate().
Very big change and not publicized widely. Microsoft has not released any motivation for this that I know of, I assume that the basic reason was WinRT (aka UWP), lots of memory management nastiness to get C++, C# and Javascript code to work together seamlessly. This is quite convenient to everybody that has to write interop code, you can now assume that Marshal.FreeHGlobal() gets the job done. Or Marshal.FreeCoTaskMem() like the pinvoke marshaller uses. Or free() like the native code would use, no difference anymore.
But also a significant risk, you can no longer assume that the code is bug-free when it works well on your dev machine and must re-test on Win7. You get an AccessViolationException if you guessed wrong about the release function. It is worse if you also have to support XP or Win2003, no crash at all but you'll silently leak memory. Very hard to deal with that when it happens since you can't get ahead without changing the native code. Best to get it right early.
I have implemented a COM component in C#:
[ComVisible(true)]
[System.Runtime.InteropServices.Guid("E052BB1C-7ADC-47F4-99E1-9407E2FA0AA2")]
public interface IColorRamps
{
IColorRamp getColorRamp();
}
[ComVisible(true)]
[Guid("EE47F2F2-0AD9-437C-8815-D570EACF2C07")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ColorRamps.ColorRamps")]
public class ColorRamps : IColorRamps
{
public IColorRamp getColorRamp() { ... }
}
I call this from C++:
IColorRampPtr colorRamp;
{
ColorRamps::IColorRampsPtr colorRamps(ColorRamps::CLSID_ColorRamps);
HRESULT hr = colorRamps->getColorRamp(&colorRamp);
colorRamp.AddRef(); // Should I do this??
}
At first I did not have the AddRef() call and things seemed to work except I got strange crashes on "R6025 (pure virtual function call) run-time error" after running this code many times.
The signature in the autogenerated .tlh file is:
virtual HRESULT __stdcall getColorRamp(/*[out,retval]*/ struct IColorRamp * * pRetVal ) = 0;
When calling functions like this in C++ I am used to the function doing an AddRef() itself and passing on memory ownership to the caller. Is this not the case in C# COM?
I did NOT call Marshal.AddRef() inside ColorRamps.getColorRamp().
That is most likely to happen because you Release() the pointer than because .NET forgot to AddRef() before returning (hint: .NET surely did not forget this).
IColorRampPtr is itself a smart pointer, you must be using it because you #imported the .NET generated type library in VC++. As such, you should never call Release() on the smart pointers, as it'll be released when it goes out of scope (or, if used in a class member, when the object is destroyed).
If you want a raw pointer, on which you must later call Release(), use the raw interface pointer (e.g. IColorRamp*) or Detach() the smart pointer. Generally, you need a raw interface pointer when its scope becomes indeterminate. If the scope is well defined and you can use a smart pointer, keep it as a smart pointer.
From MSDN (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.addref%28v=vs.80%29.aspx) :
The common language runtime manages the reference count of a COM
object for you, making it unnecessary to use this method directly. In
rare cases, such as testing a custom marshaler, you might find it
necessary to manipulate an object's lifetime manually. After calling
AddRef, you must decrement the reference count by using a method such
as Marshal.Release. Do not rely on the return value of AddRef, as it
can sometimes be unstable.
Worth a look?
I'm PInvoking a native C++ DLL. Actually I've done it twice (two different C# programs, two different C++ programs). Both times I create the memory on the C# side. Both times I used fairly complex marshalled structs which I send by ref.
However, one of my programs run just fine.
The other one runs until the native C++ attempts to read a value from the data sent. But then explosion, I'm hit with a read/write protected memory error?
I don't understand how two programs built with the same Visual Studio, can result in one letting me access the memory and the other prohibited.
I've checked settings, both are pretty much identical in project settings?
In the project I'm having problems, I even reduced the data sent to an exactly sized structure like so:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct Shared2_s
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public byte[] filler2;
//40
}
If you need the Shared2_s instance to have a lifetime longer than just the call to the native method, you'll need to allocate it in unmanaged memory and clean it up again when done.
var pointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Shared2_s)));
var inst = new Shared2_s();
Marshal.StructureToPtr(inst, pointer, false);
...
MyNativeMethod(pointer);
...
Marshal.FreeHGlobal(pointer);
The DllImport declaration of MyNativeMethod should be adjusted so that instead of taking a ref Shared2_s parameter, it takes an IntPtr instead.
You should only call FreeHGlobal after you are certain that no other native code will attempt to access the allocated memory.
For this kind of stuff I use a MemoryMappedFile and a named Mutex - no marshalling involved, just some bytes in memory which can be read/written to by anyone with the correct permissions and knowledge of the name of the MemoryMappedFile .
[EDIT] For the C++ side of this see the MSDN example here. [/EDIT]
I am using COM in my C# .NET project.
However one of the methods I call is not acting as expected.
So I am curious to see what is happening between my .NET code, the Interop layer and COM.
I know the tlbimp.exe generates the metadata wrapper for the COM component and I can see these generated methods in the Object browser.
Am I able to see/debug what happens when one of these wrapper methods is called?
I pass an Array to the method below, and expect that this array will be populated, however the Array does not get populated.
I am calling the following tlbimp.exe generated method with unexpected results:
int GetTags(System.Array buffer)
Member of CServer.IUser
Method IDL:
[id(0x000000d5)]
HRESULT GetTags(
[in] SAFEARRAY(long) buffer,
[out, retval] long* retval);
.NET code calling this method:
Array tagsArray = Array.CreateInstance(typeof(int), tagsLength);
userWrapper.GetTags(tagsArray);
Other COM methods I call work fine. However when I call any method which expects an Array as a parameter it does not work as expected.
I am presuming that there is something funny going in with the COM interop marshaller.
So I would like to know if I can see what is happening after I call the GetTags() method.
Also I have read the following here.
"if you are not satisified with the COM Interop marshaller, you can "override" just about every aspect of it through the very large and useful System::Runtime::InteropServices namespace"
How can I achieve the above?
EDIT: Adding a Delphi test script which works
procedure TComTestForm.TestUserBtnClick(Sender: TObject);
var
nCnt :integer;
User :IUser;
Persona :IUserPersona;
ArrayBounds :TSafeArrayBound;
ArrayData :Pointer;
TagList :PSafeArray;
nSize :integer;
begin
User := Session.GetUser;
ArrayBounds.lLbound := 0;
ArrayBounds.cElements := 0;
TagList := SafeArrayCreate( varInteger, 1, ArrayBounds );
User.GetTags( TagList );
if SafeArrayAccessData( TagList, ArrayData ) = S_OK then
begin
nSize := TagList.rgsabound[0].cElements;
OutLine( '----Available Tags, ' + IntToStr(nSize) + ' tags' );
for nCnt := 0 to nSize - 1 do
begin
OutLine( IntToStr( IntegerArray(ArrayData)[nCnt] ) );
end;
OutLine( '----');
SafeArrayUnAccessData( TagList );
SafeArrayDestroy( TagList );
end;
end;
Another update:
I just realize it might be that you mean that the GetTags itself should populate that Array (from the COM code). But this can never work as that parameter is an [in] parameter.
For the COM component to be able to fill up that Array, It should be passed as an [in, out] parameter, and by reference (SAFEARRAY*).
Update: Ok, apparently I was mixing the creation of a COM component in .NET with calling a COM component from .NET.
The CCW (com callable wrapper) indeed takes a .NET Array for COM SafeArray's. I see you create your array in the code in your question, but you don't show how you actually populate it. Maybe something's wrong with that code? Could you share it?
Not sure if this is a solution to your problem, but I've experienced problems with COM-interop and SAFEARRAY's in the past.
One thing I learned from it is that the .NET equivalent of a COM SAFEARRAY should always be object, so try passing your array as an object in stead of as an Array.
I hesitate to suggest this as an answer, but...
If the Delphi test code really does work, as noted elsewhere, this means the GetTags method must not be playing properly by SAFEARRAY rules. If the COM method is always called in-process, you MAY be able to get the .NET code to work by doing some custom marshalling "by hand", following exactly what the unmanaged Delphi test code does.
As a rough outline, I would imagine that this would involve:
allocating an unmanaged buffer to hold the array values
calling Ole Automation SAFEARRAY initialization APIs via P/Invoke to allocate a SAFEARRAY structure and attach the array buffer to it as its pData member
invoking the GetTags method with this SAFEARRAY
marshalling your unamanaged buffer into a managed array, before...
calling the Win32 API to destroy the SAFEARRAY
But much better to get the COM component changed to do things properly, if you can.
I have a C++ console Exe which does some progamming. Now i wanted to write a C# GUI which does some of the programming that the C++ exe does. I was thinking of few approaches,
Write the C# GUI with all programming in C++ done from scratch.(I do not want to do this for the amount of rework it entails)
Build a C++ dll which does the programming and have it imported in GUI app.(Now here i have a concern. How do i capture the output of the routines in c++ dll and display it in GUI? Should i return the output as string for every routine that the app calls.? Since i dont know managed c++ iam going to build an unmanaged C++ dll. )
Building a C++/CLI dll really isn't that hard. You basically use unmanaged C++ code except that you define a "public ref class" which hosts the functions you want the C# code to see.
What kind of data are you returning? Single numbers, matrices of numbers, complex objects?
UPDATE: Since it has been clarified that the "output" is iostreams, here is a project demonstrating redirection of cout to a .NET application calling the library. Redirecting clog or cerr would just require a handful of additional lines in DllMain patterned after the existing redirect.
The zip file includes VS2010 project files, but the source code should also work in 2005 or 2008.
The iostreams capture functionality is contained in the following code:
// compile this part without /clr
class capturebuf : public std::stringbuf
{
protected:
virtual int sync()
{
// ensure NUL termination
overflow(0);
// send to .NET trace listeners
loghelper(pbase());
// clear buffer
str(std::string());
return __super::sync();
}
};
BOOL WINAPI DllMain(_In_ HANDLE _HDllHandle, _In_ DWORD _Reason, _In_opt_ LPVOID _Reserved)
{
static std::streambuf* origbuf;
static capturebuf* altbuf;
switch (_Reason)
{
case DLL_PROCESS_ATTACH:
origbuf = std::cout.rdbuf();
std::cout.rdbuf(altbuf = new capturebuf());
break;
case DLL_PROCESS_DETACH:
std::cout.rdbuf(origbuf);
delete altbuf;
break;
}
return TRUE;
}
// compile this helper function with /clr
void loghelper(char* msg) { Trace::Write(gcnew System::String(msg)); }
So you just want to call c++ library from managed .net code?
Then you would need to either build a COM object or a p-invokable library in c++. Each approach has it's own pros and cons depending on your business need. You would have to marshall data in your consumer. There are tons and tons of material on both concepts.
Possibly relevant: Possible to call C++ code from C#?
You could just write a C# GUI wrapper (as you suggest in option 2) and spawn the C++ process; however, this will be a little slow (I don't know if that matters).
To run your C++ exe and capture the output you can use the ProcessRunner I put together. Here is the basic usage:
using CSharpTest.Net.Processes;
partial class Program
{
static int Main(string[] args)
{
ProcessRunner run = new ProcessRunner("svn.exe", "update");
run.OutputReceived += new ProcessOutputEventHandler(run_OutputReceived);
return run.Run();
}
static void run_OutputReceived(object sender, ProcessOutputEventArgs args)
{
Console.WriteLine("{0}: {1}", args.Error ? "Error" : "Output", args.Data);
}
}
See the first comment in this page to redirect stderr
Probably the best way to go here is use P/Invoke or Platform Invoke. Depending on the structure or your C++ dll interface you may want to wrap it in a pure C interface; it is easiest if your interface uses only blittable types. If you limit your dll interface to blittable types (Int32, Single, Boolean, Int32[], Single[], Double[] - the basics) you will not need to do any complex marshaling of data between the managed (C#) and unmanaged (C) memory spaces.
For example, in your c# code you define the available calls in your C/C++ dll using the DllImport attribute.
[DllImport, "ExactDllName.dll"]
static extern boolean OneOfMyCoolCRoutines([In] Double[] x, [In] Double[] y, [Out] Double result)
The little [In]'s and [Out]'s are not strictly required, but they can speed things along. Now having added your "ExactDllName.dll" as a reference to your C# project, you can call your C/C++ function from your C# code.
fixed(Double *x = &x[0], *y = &y[0] )
{
Boolean returnValue = OneOfMyCoolCRoutines(x, y, r);
}
Note that I'm essentially passing pointers back and fourth between my dll and C# code. That can cause memory bugs because the locations of those arrays may be changed by the CLR garbage collector, but the C/C++ dll will know nothing of it. So to guard against that, I've simply fixed those pointers in my C#, and now they won't move in memory while my dll is operating on those arrays. This is now unsafe code and I'll need to compile my C# code w/ that flag.
There are many fine details to language interop, but that should get you rolling. Sticking to a stateless C interface of blittable types is a great policy if possible. That will keep your language interop code the cleanest.
Good luck,
Paul