您的位置:首页 > 编程语言 > C语言/C++

C# 调用C++ dll 方法返回char* 乱码

2013-09-26 10:57 591 查看
直接上代码

C++ 代码中
#define MEDUSA_EXPORT_API __declspec(dllexport)
static char[1024*2] buff;//使用静态数组返回才不会乱码,即使在调用方法中使用堆内存也会被释放,所以声明全局静态编辑

MEDUSA_EXPORT_API char* getChar()
{
std::string a = "hello";
strcpy(buff,a.c_str());
return buff;
}


C# 代码中
public delegate InPtr getChar();//使用动态指针做返回值
private readonly DllImporter mDll = new DllImporter();
public void runDll()
{
string dllpath = "xxxx.dll";
mDll.Open(dllpath);
InPtr p = mDll.Invoke<getChar,InPtr>();
string str = Marshal.PtrToStringAnsi(p);
}


DllImporter.cs 代码如下

namespace MedusaSimulator
{
class DllImporter
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string path);

[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr lib, string funcName);

[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr lib);

private IntPtr mDll = IntPtr.Zero;

public bool IsLoaded
{
get
{
return mDll != IntPtr.Zero;
}
}
public DllImporter()
{
}

public void Open(string path)
{
if (mDll == IntPtr.Zero)
{
mDll = LoadLibrary(path);
}
}

public void Close()
{
if (mDll != IntPtr.Zero)
{
FreeLibrary(mDll);
mDll = IntPtr.Zero;
}

}

private readonly Dictionary<Type, MethodInfo> mMethods = new Dictionary<Type, MethodInfo>();

public T InvokeMethod<T>() where T : class
{
var methodType = typeof(T);
var methodPtr = GetProcAddress(mDll, methodType.Name);
var callback = Marshal.GetDelegateForFunctionPointer(methodPtr, methodType);
return callback as T;
}

public TR Invoke<T, TR>(params object[] parameters) where T : class
{
var delegateType = typeof(T);
if (mMethods.ContainsKey(delegateType))
{
var methodInfo = mMethods[delegateType];
return (TR)methodInfo.Invoke(null, parameters);
}

var myAssemblyName = new AssemblyName { Name = "DllImporter" };
var myAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(myAssemblyName, AssemblyBuilderAccess.Run);
var myModuleBuilder = myAssemblyBuilder.DefineDynamicModule("DllImporter");

var delegateMethod = delegateType.GetMethod("Invoke");
var paramInfos = delegateMethod.GetParameters();
var paramTypes = paramInfos.Select(parameterInfo => parameterInfo.ParameterType).ToArray();

var methodPtr = GetProcAddress(mDll, delegateType.Name);

var myMethodBuilder = myModuleBuilder.DefineGlobalMethod(delegateType.Name, MethodAttributes.Public | MethodAttributes.Static, delegateMethod.ReturnType, paramTypes);
var il = myMethodBuilder.GetILGenerator();
for (var i = 0; i < paramInfos.Length; i++)
{
il.Emit(OpCodes.Ldarg, i);  //by value
//IL.Emit(OpCodes.Ldarga, i);   //by ref
}

il.Emit(OpCodes.Ldc_I4, methodPtr.ToInt32());

il.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, delegateMethod.ReturnType, paramTypes);
il.Emit(OpCodes.Ret);
myModuleBuilder.CreateGlobalFunctions();

var myMethodInfo = myModuleBuilder.GetMethod(delegateType.Name);
mMethods[delegateType] = myMethodInfo;

return (TR)myMethodInfo.Invoke(null, parameters);

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: