【发布时间】:2013-03-09 13:23:18
【问题描述】:
我一直在开发一些 DLL 实用程序项目,以避免在其他项目中重复代码,以及我尚未尝试过的功能、算法和测试。其中一个项目是 C++/CLI,我仍在学习的语言,所以这个问题可能听起来很愚蠢。因为我有 C++/CLI、F# 和 C# 中的库项目,所以我使用 C# 控制台应用程序来测试它们。它不适用于 C++/CLI 项目,因此我创建了一个 C++/CLI 控制台测试项目。它从来没有用过,当我更改原始 DLL C++ 的名称时,引用没有更新。当我(最终)发现问题时,我更改了 .vcxproj 文件,使 using 指令成为可能,作为一种方法,但不适用于模板类 Apont<typename T>,它是某种内部指针,但与.NET 类型 System::IntPtr,使用 T* 类型的值而不是 void*。
我还发现(从本网站的一篇文章中)我必须在项目内部使用我想在外部使用的东西,否则这些东西想要在元数据中发出。因此,为此目的,我在静态实用程序中有一个无用的静态方法:
static void Funcionalidades()
{
int i = 10;
Apont<int> a2 = Apont<int>(i); // stack
Apont<int> ^a3 = gcnew Apont<int>(i); // heap CLR
}
然而,它不起作用。这是我在 C++/CLI 测试项目中的主要方法:
int main(array<System::String ^> ^args)
{
int y(10);
Apont<int> a = Apont<int>(y);
Console::ReadKey();
return 0;
}
以下是错误(我知道它可以用智能感知错误编译,但我还是会显示它们):
error C2065: 'Apont' : undeclared identifier
error C2062: type 'int' unexpected
IntelliSense: identifier "Apont" is undefined
IntelliSense: type name is not allowed
IntelliSense: expected an expression
为什么会出现这些错误?我该如何纠正它们?
如果有任何答复或回复,我将不胜感激。
编辑(澄清):
- 这些错误不会发生在
Funcionalidades方法上,即在 DLL 项目中,而是在 main 方法上,即在 DLL 之外,在测试项目中。 - 我正在头文件中写入所有内容;我的意思是不是每个头文件都有各自的 .cpp 文件,尽管所有头文件都包含在至少一个 .cpp 文件中。
- 更多关于
Apont:-
Apont是一个模板(因为在内部使用了 T* 并且“不允许对泛型类型参数进行间接引用”)。 -
Apont有一个复制构造函数,所以Apont<int> a = Apont<int>(someInt)应该可以工作; -
Apont<int> a(someInt)不起作用; -
Apont是某种内部指针;而且我没有发布整个代码,因为它不相关,我必须翻译变量的名称,它可能有我可以轻松修复的错误,但这只会分散你的注意力。
-
NTH EDIT('n' 是一个我不知道的数字):
Apont的代码你抱怨了这么久:
template<typename T> public ref class Apont sealed : public IDisposable
{
bool eliminado;
T *pointer;
/*void Dispose(bool tudo)
{
if (!eliminado)
{
if (tudo)
{
~Apont();
}
else
{
!Apont();
}
}
}*/
!Apont() // finalizador: limpa os recursos "unmanaged"
{
delete pointer;
pointer = nullptr;
eliminado = true;
}
public:
Apont(T &valor)
{
pointer = &valor;
eliminado = false;
ErroSeNulo = false;
ErroSeEliminado = true;
}
Apont(T &valor, bool erroSeEliminado, bool erroSeNulo)
{
pointer = &valor;
eliminado = false;
ErroSeEliminado = erroSeEliminado;
ErroSeNulo = erroSeNulo;
}
Apont(Apont<T> %outroApont)
{
this->pointer = &outroApont
}
property bool ErroSeEliminado;
property bool ErroSeNulo;
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado)
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo)
throw gcnew NullReferenceException();
else
return 0;
}
}
/*
Apont operator ~(/*T valor* /)
{
// este operador tem de ser declarado fora desta classe
}*/
T operator !(/*Apont apont*/)
{
return Valor;
}
void operator =(Apont<T> outroApont)
{
pointer = outroApont;
ErroSeEliminado = outroApont.ErroSeEliminado;
ErroSeNulo = outroApont.ErroSeNulo;
}
template<typename U> void operator =(Apont<U> outroApont)
{
pointer = safe_cast<T>(outroApont.pointer);
ErroSeEliminado = safe_cast<T>(outroApont.ErroSeEliminado);
ErroSeNulo = safe_cast<T>(outroApont.ErroSeNulo);
}
/*
void operator =(T *&outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *&outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}*/
void operator =(T *outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}
~Apont() // destruidor: limpa todos os recursos
{
this->!Apont();
}
// Error C2605: 'Dispose': this method is reserved within a managed class
// O código será gerado automaticamente a partir do finalizador e do destrutor
};
template<typename T> Apont<T> operator ~(T &valor)
{
return gcnew Apont<T>(valor);
}
【问题讨论】:
-
您可能应该创建一个short, self-contained, correct example。您的问题中缺少或未说明的内容太多,这是回答所必需的。如果您按照上面链接中的建议进行操作,我相信您会收到更多回复。
-
当编译成 dll 时,函数名称/签名可能会在 c++ 中被破坏,您需要找到它们在 dll 中的内容并创建指向它们的链接,例如通过以下方式从 dll 中发现内部名称使用
link /dump /exports mydll.dll。使用我之前提到的链接命令检查您希望出现的值和函数是否实际存在于您的 dll 中。让我知道你的进展情况,我会尽力帮助你解决这个问题。 -
嗨,是的,你从命令行使用它。 id 建议导航到 dll 所在的目录并仅使用链接 /dump/exports mydll.dll 而不必在命令后键入完整路径:)
-
我明白了,刚刚注意到我的一些 dll 也在做同样的事情,并且不得不关闭调试信息`属性,链接器,调试,生成调试信息 = 否`,所以名称没有被破坏。并且正确可见。在旁注中,dumpbin.exe 做了类似的工作(VS 命令行),或者dependency walker 有一个很好的 gui 来实现同样的效果。我正在研究这个隐藏的函数名称问题,因为我自己的一些 dll 也有同样的问题,但是这些函数在我导入 dll 时可以使用......非常奇怪。
-
Utilidades.ComNativos是我查看 dll 的命名空间,Apont根本没有暴露,但是UtilCMM是,也许看看这两个类有什么区别? (起点可能是:apont 是密封类,utilscmm 是静态类)
标签: .net pointers c++-cli wrapper