C++ CLI 错误 C3767:候选函数无法访问
我是来自非托管 C++ 世界的 C++ CLI 新手。
我收到此错误:
candidate function(s) not accessible
当我传递 std::string 作为方法参数的一部分时。
确切的代码如下:
Lib Project(编译为.dll项目)
//Lib.h
#pragma once
public ref class Lib
{
public:
Lib(void);
public:
void Extract( std::string& data_ );
};
//Lib.cpp
#include "Lib.h"
Lib::Lib(void)
{
}
void Lib::Extract( std::string& data_ )
{
data_.empty();
}
LibTest Project(编译为application.exe)
// LibTest .h
#pragma once
ref class LibTest
{
public:
LibTest(void);
};
// LibTest.cpp
#include "LibTest.h"
LibTest::LibTest(void)
{
Lib^ lib = gcnew Lib;
lib->Extract( std::string("test") );
}
int main()
{
return 0;
}
编译器错误:
1>------ Build started: Project: LibTest, Configuration: Debug Win32 ------
1>Compiling...
1>LibTest.cpp
1>.\LibTest.cpp(7) : error C3767: 'Lib::Extract': candidate function(s) not accessible
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您只需要访问
内部
方法,另一种解决方法是将项目制作为Friend Assemblies 像这样://Lib Project
//LibTest Project
if you simply must access the
internal
methods another work around would be making the projects as Friend Assemblies like that://Lib Project
//LibTest Project
问题是 std::string 将编译为内部(非公共)类型。 这实际上是 VS 2005+ 中的更改:
http:// msdn.microsoft.com/en-us/library/ms177253(VS.80).aspx:
默认情况下,本机类型在程序集外部是私有的
默认情况下,本机类型现在在程序集外部不可见。 有关程序集外部类型可见性的详细信息,请参见类型可见性。 此更改主要是由使用其他不区分大小写的语言的开发人员在引用用 Visual C++ 编写的元数据时的需求驱动的。
您可以使用 Ildasm 或 reflector,您将看到您的 extract 方法被编译为:
basic_string 被编译为:
注意内部。
不幸的是,您无法从不同的程序集中调用这样的方法。
在某些情况下有一个解决方法:您可以使用 make_public pragma 强制将本机类型编译为公共类型。
例如,如果您有一个方法 Extract2,例如:
您可以通过预先包含此 pragma 语句来强制将 std::exception 编译为公共:
此方法现在可以跨程序集调用。
不幸的是 make_public 不适用于模板化类型(std::string 只是 basic_string<> 的 typedef)
我不认为你可以做任何事情来让它发挥作用。 我建议在所有公共 API 中使用托管类型 System::String^。 这还确保您的库可以轻松地从其他 CLR 语言(例如 c#)调用
The problem is that std::string will compile as a internal (non public) type. This is actually a change in VS 2005+:
http://msdn.microsoft.com/en-us/library/ms177253(VS.80).aspx:
Native types are private by default outside the assembly
Native types now will not be visible outside the assembly by default. For more information on type visibility outside the assembly, see Type Visibility. This change was primarily driven by the needs of developers using other, case-insensitive languages, when referencing metadata authored in Visual C++.
You can confirm this using Ildasm or reflector, you will see that your extract method is compiled as:
with basic_string being compiled as:
Note the internal.
Unfortunately you are then unable to call a such a method from a different assembly.
There is a workaround available in some cases: You can force the native type to be compiled as public using the make_public pragma.
e.g. if you have a method Extract2 such as:
you can force std::exception to be compiled as public by including this pragma statement beforehand:
this method is now callable across assemblies.
Unfortunately make_public does not work for templated types (std::string just being a typedef for basic_string<>)
I don't think there is anything you can do to make it work. I recommend using the managed type System::String^ instead in all your public API. This also ensures that your library is easily callable from other CLR languages such as c#
除了上述解决方案之外,还可以对模板化类型进行子类化以获得非模板化类型,并将其定义包含在两个项目中,从而克服上述一些问题。
In addition to the solutions described above, one can subclass the templated type to obtain a non-templated type, and include its definition in both projects, thus overcoming some of the problems mentioned above.