I am new to using C++ libraries in C# and also to the C++ programming in general. I have a DLL built from a C++ code which I believe is a 'managed' code as the name of the DLL is "TestManaged.dll". I am not 100% sure if the dll/C++ code is managed/unmanaged.
I want to use classes and methods of this DLL in my C# windows forms application
code. There are multiple classes in this DLL. When I chekced these classes and methods inside those classes in Object Browser
, all of them have Public
identifier.
So far, I have added this DLL to my references of C# application code. There are three classes I would talk about in my question: Product
, ReqStatus
, ProductData
. I could create an object(s) for various classes of this DLL as follows.
Product testCall = new ProductClass();
There is another class called ProductData
in this DLL and I could get the C++ code for this class which is as follows. In this case, ProductData
is shown as class in Object Browser
in C# where as it is actually a struct in C++ code. I am not sure if this is important to answer my question (at the end).
Following is a C++ code that defines ProductData
struct - ProductData.h
file.
#ifdef WIN32_MANAGED
public ref struct ProductData
#else
struct ProductData
#endif
{
UINT32 ProductId; //!< Product ID
UINT32 PRoductRev; //!< Build Revision
};
Following is a C++ code that defines ReqStatus
enum - ReqStatus.h
file. I have created the same enum in my C# code with no identifier specified.
enum ReqStatus
{
SUCCESS, //!< Method was successful
//Connection errors
NOT_CONNECTED, //!< Connection not open
CONN_TIMEOUT, //!< Connection timed out commuincating with device
};
Now, there are two methods I want to call and have problems with both:
Method 1: is a getProductData
method inside Product
class which accepts object of ProductData
type as a parameter and returns the ReqStatus
which is an enum type in C++. So following is the declaration of the gerProductData
method (as seen in the Object Browser
):
public ReqStatus getProductData(ProductData data)
The same method's C++ delcaration is: (The actual method is too long and hence just giving the declaration): This method is inside Prodcut.cpp
file
ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)
PLATFORM_PTR is defined as below in Platform.h
#ifdef WIN32_MANAGED
#define PLATFORM_PTR ^
#else
#define PLATFORM_PTR *
#endif
Method 2: is a getConnected
method inside Product
class which accepts a character array (I am not sure of this) and an object of ProductData
type as a parameter and returns the ReqStatus
which is an enum type in C++. So following is the declaration of the getConnected
method (as seen in the Object Browser
):
public ReqStatus getConnected(sbyte* someChar, ProductData data)
The same method's C++ delcaration is: (The actual method is too long and hence just giving the declaration): This method is inside Prodcut.cpp
file
ReqStatus Product::getConnected(const char *someChar, ProductData PLATFORM_PTR data)
C++ code calls the methods as follows:
private : Product^ _testProduct;
testProduct = gcnew Product();
ProductData ^ data = gcnew ProductData();
int portNum = Decimal::ToInt16(7);
char portName[32];
_snprintf(&portName[0], sizeof(portName),"COM%d", portNum);
ReqStatus status = _testProduct->getConnected(&portName[0], data); //Calling getConnected
There is an internal call to getProductData
method inside the getConnected
method.
ReqStatus status = getProductData(data); //data is the same which was passed to the getConnected method
MY C# code is as follows and I got errors at both method calls: I have put errors on the same line in the below code snippet. Both methods are independent. Its just that the getProductData
is called from getConnected
method in C++ code. I wanted to check if I can call both individually.
ProductData pData = new ProductData(); // OK
Product _testProduct = new Product(); // OK
ReqStatus status1 = _testProduct.getConnected("COM5", pData ); //Error 1: The best overloaded method getConnected has some invalid arguments
ReqStatus status2 = (ReqStatus)_testProduct.getProductData(pData ); // Error 2: Method is inaccessible due to its protection level
For Error 1, I tried solutions from various articles on StackOverflow and other forums but, could not solve it. Just for a reference, I tried to change the "SomePortCOM" as follows but it din't work.
UPDATE: This code works fine now and I don't see Error 1(Invalid arguments). Now, I only need to get rid of the Error 2 (Protection level error). Kindly provide any suggestions. Thank you.
String str = "COM5";
byte[] bytes = Encoding.ASCII.GetBytes(str);
unsafe
{
fixed (byte* p = bytes)
{
sbyte* sp = (sbyte*)p;
//SP is now what you want
ReqStatus status1 = _testProduct.getConnected(sp, pData );
}
}
For Error2, I searched so many blogs and found that one of the possible solution could be the use of DLLImport, I tried that as well and I have following issue:
C# declaration of DLLImport:
[DllImport("TestManaged.dll",EntryPoint="getConnected")]
public static extern ReqStatus getConnected(String SerialPort, ref ProductData pData);
I am calling this function as below from my C# code:
ProductData pData = new ProductData();
String str = "COM7";
ReqStatus status1 = getConnected(str, ref pData);
However, I am getting Entry point not found
error. I tried to run the dumpbin function to get the list of functions exported by this DLL. But, I do not see any functions. Rather just a random output as below.
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\Rumit\TestManaged.dll
File Type: DLL
Summary
2000 .data
22000 .rdata
1000 .reloc
1000 .rsrc
13000 .text
UPDATE: Also, I do not see any methods in this DLL via Dependency Walker. Now, I have got the source code for C++. But I am fairly new to C++ coding. In case any change is required to C++ code, kindly give the directions.
Regards, Rumit