I'm trying to port a C++.NET (managed extensions) application to C++/CLI. However I'm not very strong with the syntax yet.
What I'm trying to do is to create a wrapper for a C Dll file.
To do this I'm using DllImport but I failed to found documentation on it's use. There are some problems due to changes of the syntax but I couldn't find out why yet.
The C++.NET line looks like this:
[DllImport("my.dll", CharSet = Ansi, CallingConvention = Cdecl, EntryPoint = "#10")]
static MY_STATUS CPPInit(MY_HANDLE *pLmxHandle);
The idea is to pass a reference of MY_HANDLE to the function which initializes it. One problem is that the keywords Ansi and Cdecl are unknown. I expect I need to put some class infront of them but it's a little hard without docs or samples.
The other thing I have is a function which returns a static string:
char *MyFunc();
Can I assume that it can be mapped to String^?
Thanks in advance.
thanks for the comment.
I thought to myself that I need to build a mixedmode library in order to avoid p/invoke. This just takes some time though.
Actually I solved the compile error in another way. Although I havn't tested it yet because I'm facing some 32/64 bit issues which I can't solve because of other bugs in Whidbey beta2.
My solution was to write the protype in the following way:
interior_ptr<MY_HANDLE> pMyHandle;
From what I understood it should give the function a reference (hence an address) to the dll function. Once I get to try it out I will see if my idea works.
Otherwise I will go for the following option (which i've been offered):
[Out] IntPtr p_MyHandle
Anyway I think the problem is solved because one of those should work.
Related
I am creating a C++/CLI wrapper for native C code that has it's own Object typedef and am receiving the C2872 'Object': ambiguous symbol error when linking. The compiler output is:
1>C:\src\OS_kernel.h(27): error C2872: 'Object': ambiguous symbol
1>C:\src\OS_types.h(261): note: could be 'ObjectStruct *Object'
1>C:\src\OS_kernel.h(27): note: or 'System::Object'
It may be worth mentioning that I am mocking this native C code for the purposes of the C++/CLI wrapper; not sure if that opens up a potential solution that would otherwise not be available if no source code was available. I'm guessing there is a way to specify which definition I want the code to use, but I don't know how to specify that. Is that possible? I want to specify it to use the ObjectStruct *Object.
It would be great if I didn't have to modify the mock code since it could potentially be hundreds or thousands of individual places.
As an aside, I am also receiving this error for other types the native library is using, such as Buffer and Boolean.
OK, since you're getting the error in OS_kernel.h, I'm guessing that's part of the C code you're wrapping.
Obviously, one possible solution is to treat the name Object as a reserved word, and edit your C code to not use it. One could argue that this is the most correct solution, but it may not be possible to do that.
Depending on how you're referencing the C code, it may be reasonable to compile it as C++, and stick it entirely within a namespace. That way, when the C code (now C++ code) uses Object it will see the typedef within its namespace, and you'll have the option to reference either namespace in your code.
The fact that you're getting this error from your library's header file indicates to me that you've got a using namespace System; directive, and that the #include of your library's header files comes after that using directive. Consider removing the using namespace System;, or at least moving it after the #include. This way, you won't get that error in the library's headers, you'll just have to deal with it in your code.
I'm running through the libgit2 sample code for getting the content of blobs, and I've hit a problem with the line:
git_buf filtered_content = GIT_BUF_INIT;
I get error C2065: 'GIT_BUF_INIT': undeclared identifier, which makes sense, because I can't find this defined in any of the included header files. As nobody seems to have asked this question before I get the strong feeling I'm missing something obvious. Any ideas on what I need to do to use GIT_BUF_INIT?
That's declared inside the library because it references an internal buffer. You should zero the structure as usual for C.
If the examples contain GIT_BUF_INIT they were probably extracted from the tests and we missed that it's not available outside.
I have a DLL from a vendor that I Need to invoke from C#. I know that C# data classes are not directly compatible with C++ data types.
So, given that I have a function that receives data and returns a "string".
(like this)
string answer = CreateCode2(int, string1, uint32, string2, uint16);
What must I do to make the input parameters compatible, and then make the result string compatible?
Please - I have never done this: Don't give answers like "Use P/Invoke" or "Use Marshal" I need a tutorial with examples.
All the P/Invoke examples I have seen are from .NET Framework 1.1, and Marshall (without a tutorial) is totally confusing me.
Also, I have seen some examples that tell me when I create my extern function to replace all the datatypes with void*. This is makes my IDE demand that I use "unsafe".
This isn't quite a tutorial but it's got a lot of good information on using P/Invoke
Calling Win32 DLLs in C# with P/Invoke
It'll give you an idea of the terminology, the basic concepts, how to use DllImport and should be enough to get you going.
There's a tutorial on MSDN: Platform Invoke Tutorial.
But it's pretty short and to be honest the one I've mentioned above is a much better source of information, but there's a lot of it on there.
Also useful is the PInvoke Signature Toolkit, described here .
And downloadable here.
It lets you paste in an unmanaged method signature, or struct definition and it'll give you the .NET P/Invoke equivalent. It's not 100% perfect but it gets you going much quicker than trying to figure everything out yourself.
With regards to Marshalling specifically, I would say start simple.
If you've got something that's some sort of pointer, rather than trying to convert it directly to some .NET type in the method signature using Marshal it can sometimes be easier to just treat it as an IntPtr and then use Marshal.Copy, .PtrToString, .PtrToStructure and the other similar methods to get the data into a .NET type.
Then when you've gotten to grips with the whole thing you can move on to direct conversions using the Marshal attribute.
There's a good 3 part set of articles on marshalling here, here and here.
I have encountered a strange problem, which I could solve but don't understand why it did occur.
I have build a DLL with COM enabled. In this DLL I have classes that did use the functions CInt, CDec and IsNumeric. If I test these classes from a .NET application then it works ok. But when I called/run these classes from a Win32 application (with COM) then I did get an "E_UNEXPECTED(0x8000FFFF)" error.
After some debugging I found out that the problem would go away if I:
- replaced IsNumeric with Integer.TryParse or Decimal.TryParse
- replaced CInt with Integer.Parse
- replaced CDec with Decimal.Parse
Can anyone explain this? Again, I could solve it by doing this but I would like to know why.
Just a guess.
I think that this is somehow related to the fact that all legacy functions like CInt, CDec, etc are defined in Microsoft.VisualBasic.dll assembly, which appears not to be playing well with COM.
That's pretty strange. Sounds to me like the arguments passed by the unmanaged code caused an exception in the VB.NET code. Your unmanaged code cannot detect managed exceptions. It should be visible in the debug output in the Output window, you should see a first-chance exception with exception code 0xe0434f4e.
Your changes are not a true replacement for CInt/CDec, they'll only handle string arguments. But stranger yet is that CInt() doesn't have trouble with strings, it shouldn't throw.
You are playing fast and loose with argument types though, treating strings as numbers is always trouble. Make sure you declare the argument type. Putting Option Strict On at the top of your source code is a good way to operate the two-by-four.
I'm trying to use a COM library that makes use of a vtable. However, something funky is going on with the stack after I call the functions, which tells me I'm doing something wrong.
The header file with the vtable definition is pasted here: pastebin.com/m2d66c18c (see in particular the code starting at line 810). An example is pasted here: pastebin.com/m1b46e662.
The table is being filled with the correct locations for the functions, but when I call the function(s), they appear to be looking in the wrong locations for the arguments on the stack. Also, after calling the functions in the table, the stack is messed up and my program crashes. I've tried changing the function type to both __cdecl and __stdcall but this does nothing.
It's either my code or the library, and the company that wrote the library hasn't gotten back to me -- because it's the weekend, I'm assuming. Also, there is a demo application that utilizes the library, and it works -- so I think it's my code/compiler (gcc)/something else, not the library.
Could it be that there something in particular that you need to do in order to use a COM library?