C++ CLI 错误 C3767:候选函数无法访问

发布于 2024-07-22 15:36:40 字数 1154 浏览 3 评论 0 原文

我是来自非托管 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

I'm new to C++ CLI coming from unmanaged C++ world.

I'm getting this error:

candidate function(s) not accessible 

when I pass a std::string as part of the method argument.

Here's the exact code:

Lib Project (compiled as .dll project)

//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 (compiled as 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;
}

Compiler Error:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南汐寒笙箫 2024-07-29 15:36:40

如果您只需要访问内部方法,另一种解决方法是将项目制作为Friend Assemblies 像这样:

//Lib Project

#pragma once

//define LibTest as friend assembly which will allow access to internal members
using namespace System;
using namespace System::Runtime::CompilerServices;
[assembly:InternalsVisibleTo("LibTest")];

public ref class Lib
{
 public:
  Lib(void);

 public:
  void Extract( std::string& data_ );
};

//LibTest Project

#pragma once

#using <Lib.dll> as_friend

ref class LibTest
{
  public:
    LibTest(void);
};

if you simply must access the internal methods another work around would be making the projects as Friend Assemblies like that:

//Lib Project

#pragma once

//define LibTest as friend assembly which will allow access to internal members
using namespace System;
using namespace System::Runtime::CompilerServices;
[assembly:InternalsVisibleTo("LibTest")];

public ref class Lib
{
 public:
  Lib(void);

 public:
  void Extract( std::string& data_ );
};

//LibTest Project

#pragma once

#using <Lib.dll> as_friend

ref class LibTest
{
  public:
    LibTest(void);
};
迷爱 2024-07-29 15:36:40

问题是 std::string 将编译为内部(非公共)类型。 这实际上是 VS 2005+ 中的更改:

http:// msdn.microsoft.com/en-us/library/ms177253(VS.80).aspx

默认情况下,本机类型在程序集外部是私有的
默认情况下,本机类型现在在程序集外部不可见。 有关程序集外部类型可见性的详细信息,请参见类型可见性。 此更改主要是由使用其他不区分大小写的语言的开发人员在引用用 Visual C++ 编写的元数据时的需求驱动的。

您可以使用 Ildasm 或 reflector,您将看到您的 extract 方法被编译为:

public unsafe void Extract(basic_string<char,std::char_traits<char>,std::allocator<char> >* modopt(IsImplicitlyDereferenced) data_)

basic_string 被编译为:

[StructLayout(LayoutKind.Sequential, Size=0x20), NativeCppClass, MiscellaneousBits(0x40), DebugInfoInPDB, UnsafeValueType]
internal struct basic_string<char,std::char_traits<char>,std::allocator<char> >

注意内部

不幸的是,您无法从不同的程序集中调用这样的方法。

在某些情况下有一个解决方法:您可以使用 make_public pragma 强制将本机类型编译为公共类型。

例如,如果您有一个方法 Extract2,例如:

void Extract2( std::exception& data_ );

您可以通过预先包含此 pragma 语句来强制将 std::exception 编译为公共:

#pragma make_public(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:

public unsafe void Extract(basic_string<char,std::char_traits<char>,std::allocator<char> >* modopt(IsImplicitlyDereferenced) data_)

with basic_string being compiled as:

[StructLayout(LayoutKind.Sequential, Size=0x20), NativeCppClass, MiscellaneousBits(0x40), DebugInfoInPDB, UnsafeValueType]
internal struct basic_string<char,std::char_traits<char>,std::allocator<char> >

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:

void Extract2( std::exception& data_ );

you can force std::exception to be compiled as public by including this pragma statement beforehand:

#pragma make_public(std::exception)

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#

蘑菇王子 2024-07-29 15:36:40

除了上述解决方案之外,还可以对模板化类型进行子类化以获得非模板化类型,并将其定义包含在两个项目中,从而克服上述一些问题。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文