我对使用C#中的C++库以及一般的C++编程是不熟悉的。我有一个从C++代码构建的DLL,我相信它是“托管”代码,因为DLL的名称是“TestManaged.dll”。我不是100%确定dll / C++代码是否为托管/非托管。
我想在我的C# windows forms application
代码中使用此DLL的类和方法。此DLL中有多个类。当我在Object Browser
的这些类中检查这些类和方法时,它们全部都有Public
标识符。
到目前为止,我已将此DLL添加到C#应用程序代码的引用中。我将在问题中讨论三个类:Product
,ReqStatus
和ProductData
。我可以为此DLL的各种类创建一个或多个对象,如下所示。
Product testCall = new ProductClass();
在此DLL中还有另一个名为
ProductData
的类,我可以为该类获取C++代码,如下所示。在这种情况下,ProductData
在C#中的Object Browser
中显示为类,因为它实际上是C++代码中的结构。我不确定这对回答我的问题是否重要(最后)。以下是定义
ProductData
结构-ProductData.h
文件的C++代码。#ifdef WIN32_MANAGED
public ref struct ProductData
#else
struct ProductData
#endif
{
UINT32 ProductId; //!< Product ID
UINT32 PRoductRev; //!< Build Revision
};
以下是定义
ReqStatus
枚举-ReqStatus.h
文件的C++代码。我在C#代码中创建了相同的枚举,但未指定标识符。enum ReqStatus
{
SUCCESS, //!< Method was successful
//Connection errors
NOT_CONNECTED, //!< Connection not open
CONN_TIMEOUT, //!< Connection timed out commuincating with device
};
现在,我有两种方法要调用,但都存在问题:
方法1:是
getProductData
类中的Product
方法,该方法接受ProductData
类型的对象作为参数,并返回C++中为枚举类型的ReqStatus
。因此,下面是gerProductData
方法的声明(如Object Browser
所示):public ReqStatus getProductData(ProductData data)
相同方法的C++替代方法是:(实际方法太长,因此仅给出声明):此方法位于
Prodcut.cpp
文件中ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)
PLATFORM_PTR在
Platform.h
中定义如下#ifdef WIN32_MANAGED
#define PLATFORM_PTR ^
#else
#define PLATFORM_PTR *
#endif
方法2:是
getConnected
类中的Product
方法,它接受字符数组(我不确定)和ProductData
类型的对象作为参数,并返回ReqStatus
,它是C++中的枚举类型。因此,下面是getConnected
方法的声明(如Object Browser
所示):public ReqStatus getConnected(sbyte* someChar, ProductData data)
相同方法的C++替代方法是:(实际方法太长,因此仅给出声明):此方法位于
Prodcut.cpp
文件中ReqStatus Product::getConnected(const char *someChar, ProductData PLATFORM_PTR data)
C++代码按如下方式调用方法:
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
getProductData
方法内部有一个对getConnected
方法的内部调用。ReqStatus status = getProductData(data); //data is the same which was passed to the getConnected method
我的C#代码如下,在两个方法调用中都出现错误:在下面的代码片段的同一行上放置了错误。两种方法都是独立的。只是从C++代码中的
getProductData
方法调用了getConnected
。我想检查一下是否可以分别打电话给我。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
对于错误1,我尝试了StackOverflow和其他论坛上各种文章中的解决方案,但无法解决。仅供参考,我尝试按以下方式更改“SomePortCOM”,但它不起作用。
更新:该代码现在可以正常工作,并且我看不到错误1(无效的参数)。现在,我只需要摆脱错误2(保护级别错误)。请提供任何建议。谢谢。
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 );
}
}
对于Error2,我搜索了很多博客,发现可能的解决方案之一可能是使用DLLImport,我也尝试过这样做,但遇到以下问题:
DLLImport的C#声明:
[DllImport("TestManaged.dll",EntryPoint="getConnected")]
public static extern ReqStatus getConnected(String SerialPort, ref ProductData pData);
我从我的C#代码中调用此函数,如下所示:
ProductData pData = new ProductData();
String str = "COM7";
ReqStatus status1 = getConnected(str, ref pData);
但是,我收到了
Entry point not found
错误。我试图运行dumpbin函数来获取此DLL导出的函数列表。但是,我看不到任何功能。而是如下所示的随机输出。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
更新:
另外,我没有通过Dependency Walker在此DLL中看到任何方法。
现在,我已经获得了C++的源代码。但是我对C++编码还是相当陌生。如果需要对C++代码进行任何更改,请给出说明。
问候,
鲁米特
最佳答案
enum ReqStatus
那是你最大的困扰。声明了本机枚举类型,它在托管代码中不可用,并使使用它的任何代码不可访问。您必须使用enum class关键字声明其托管版本,如下所示:
public enum class ReqStatus {
// etc...
}
关于c# - 在C#Windows应用程序中使用C++ DLL:获取错误 “Entry point not found”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15508310/