如何从C++DLL导出全局变量
How to export a global variable from a C++ DLL?
问题是我试图从C#程序访问C++DLL中声明的全局变量。尽管我在一个重复调用的函数中将变量设置为15(本例中为Subtract),但每次调用getter(本例为Divide)时,返回值都是零。这是我的代码。头文件:
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
namespace MathFuncs
{
class MyMathFuncs
{
public:
static MATHFUNCSDLL_API double Add(double a, double b);
static MATHFUNCSDLL_API double Subtract(double a, double b);
static MATHFUNCSDLL_API double Multiply(double a, double b);
static MATHFUNCSDLL_API double Divide(double a, double b);
};
}
C++代码:
__declspec(dllexport) double signID; //this is my variable
__declspec(dllexport) double __cdecl MyMathFuncs::Subtract(double a, double b){
//.. some code
signID = 15; //this function is the setter
}
__declspec(dllexport) double __cdecl MyMathFuncs::Divide(double a, double b)
{
return signID; //this function is the getter, it return zero when called from C#
}
在我的C#代码中,我使用了下面的方法:http://www.quantcode.com/modules/smartfaq/faq.php?faqid=95我一直从getter函数得到一个零返回值,为什么,以及如何解决这个问题?
编辑:C#代码:
using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;
static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
public class SignDetector : MonoBehaviour
{
//Lets make our calls from the Plugin
[DllImport("CVDetectorDLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = @"?Add@MyMathFuncs@MathFuncs@@SANNN@Z")]
private static extern double add(double a, double b);
[DllImport("CVDetectorDLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = @"?Subtract@MyMathFuncs@MathFuncs@@SANNN@Z")]
private static extern double subtract(double a, double b);
[DllImport("CVDetectorDLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = @"?Multiply@MyMathFuncs@MathFuncs@@SANNN@Z")]
private static extern double multiply(double a, double b);
[DllImport("CVDetectorDLL", CallingConvention = CallingConvention.Cdecl, EntryPoint = @"?Divide@MyMathFuncs@MathFuncs@@SANNN@Z")]
private static extern double divide(double a, double b);
double myvariable;
void Start(){
subtract(0, 0); //here we invoke the setter
IntPtr mydll = NativeMethods.LoadLibrary("CVDetectorDLL.dll");
//get a pointer to unmanaged heap address
IntPtr addrUnmanagedHeap = NativeMethods.GetProcAddress(mydll, "signID");
if (addrUnmanagedHeap != IntPtr.Zero)
{
//convert and read memory from unmanaged pointer
myvariable = Marshal.ReadInt32(addrUnmanagedHeap);
}
}
void Update(){
Debug.Log("Found = " + myvariable); //prints zero
Debug.Log("Found = " + divide(0,0)); //getter
}
}
我猜(在没有看到您的c#代码的情况下)问题出在您的调用约定中。__cdecl是c++的默认值,如MSDN __cdecl所述
这意味着调用函数负责堆栈。在这种情况下,你的.net程序。c#默认为__stdcall的调用约定。这对于接受或返回参数的方法非常重要,因为它决定了堆栈的行为。
我已经包含了一些代码,这些代码应该会向您展示实现这一功能的方法。
c++代码头
#define DLLEXPORT __declspec(dllexport)
#ifdef __cplusplus
extern "C" { //Used to prevent name mangling on dll export
#endif //__cplusplus
double signID;
DLLEXPORT void __stdcall SetDoubleValue();
DLLEXPORT double __stdcall ReturnDoubleValue(double dummyone, double dummytwo);
#ifdef __cplusplus
}
#endif //__cplusplus
c++
void __stdcall SetDoubleValue()
{
signID = 15;
}
double __stdcall ReturnDoubleValue(double dummyone, double dummytwo)
{
return signID;
}
c#导入代码
[DllImport("DllExport.dll")]
public static extern void SetDoubleValue();
[DllImport("DllExport.dll")]
public static extern double ReturnDoubleValue(double dummyone, double dummytwo);
注意,如果你不能或不想从__cdecl更改,你也可以将c#定义更改为
[DllImport("DllExport.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetDoubleValue();
[DllImport("DllExport.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern double ReturnDoubleValue(double dummyone, double dummytwo);
看起来我的原始代码和发布的解决方案都能正常工作——我似乎错误地识别了DLL中没有的问题。
相关文章:
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 当vector是tje全局变量时,c++中vector的内存管理
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 内联函数中具有内部链接的全局变量
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 全局变量 多读取器 一个写入器多线程安全?
- 如果全局变量默认是外部变量,为什么要添加"extern"关键字?
- 不同作用域中的静态变量和全局变量
- 视觉C++:在 DLL 加载期间,全局变量初始化顺序是否具有确定性?
- 在链接到两个 exe 的 dll 中共享全局变量
- 全局外部指针变量在 DLL 中不可见
- DLL libarry 中相同的静态和全局变量
- 如何从C++DLL导出全局变量
- DLL 中具有多个类和全局变量的多个 DLL
- 在同一DLL的实例之间共享静态和全局变量
- c#中如何从带有全局变量的c++ dll函数中获取返回数组
- DLL的全局变量存储在内存中
- DLL中使用的全局变量
- 在DLL和exe中使用全局变量
- 在DLL中定义的全局变量和宿主软件的全局变量