这是我在DLL中的函数的签名:
int __stdcall myFun( void * const context, const char * const pszFileName, const unsigned int buffSize, void * const pWaveFormatex );
Run Code Online (Sandbox Code Playgroud)
所有参数均为[in].用户应该通过WAVEFORMATEX最后一个参数传递指向结构的指针.返回后,它将被填补.所有这些在C++中都很有效.
现在,我正在尝试使用C#中的相同DLL,但它根本不起作用.问题出在最后一个参数中.由于我根本不了解C#,我想问一下这是否可行.如果是的话,我会很感激一个例子.
我最后一次尝试是这样的:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
public ushort cbSize;
}
Run Code Online (Sandbox Code Playgroud)
注意:我还使用Struct Member Alignment = 1构建了我用C++编写的DLL.也许我很愚蠢,但我认为Pack = 1上面的内容与C++相关,但我不知道它是不是......
[DllImport("myLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern int myFun( IntPtr context,
[MarshalAs( UnmanagedType.LPStr )]
string pszFileName,
int bufferSize,
ref IntPtr pWfx );
IntPtr unmanaged_pWfx = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WAVEFORMATEX)));
result = DLLWrapper.myFun(context,
"C:\\video.wmv",
176400,
ref unmanaged_pWfx );
WAVEFORMATEX wfxFormat = (WAVEFORMATEX)Marshal.PtrToStructure( unmanaged_pWfx, typeof(WAVEFORMATEX));
Run Code Online (Sandbox Code Playgroud)
行为未定义.有时它会挂起,有时它会终止......有些事情是非常错误的.但是,问题不在DLL中,问题出在C#端.C#是否能够使用指针?
感谢您提供的任何反馈.
编辑(工作C++代码):
void * context;
WAVEFORMATEX wfx;
int success = getContext( &context );
success = myFun( context, "C:\\video.wmv", 176400, &wfx );
Run Code Online (Sandbox Code Playgroud)
C#中的等价物是:
IntPtr context;
WAVEFORMATEX wfx;
int success = getContext( out context );
success = myFun( context, "C:\\video.wmv", 176400, out wfx );
extern "C" __stdcall int getContext( void ** pContext );
[DllImport("myLib.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int getContext(out IntPtr context);
Run Code Online (Sandbox Code Playgroud)
那么,根据你提供的信息,我会说你需要像这样声明C#函数:
[DllImport("myLib.dll")]
public static extern int myFun(
IntPtr context,
string fileName,
uint bufferSize,
out WAVEFORMATEX wfx
);
Run Code Online (Sandbox Code Playgroud)
并调用这样的函数:
WAVEFORMATEX wfx;
int result = DLLWrapper.myFun(context, @"C:\video.wmv", 176400, out wfx);
Run Code Online (Sandbox Code Playgroud)
实际上不需要手动编组此结构.这是一个非常简单的blittable结构,让框架处理编组更加清晰.
当您声明最终的struct参数不需要初始化并且其成员由函数填写时,我假设您是准确的.
包装看起来合理.我认为你不需要以任何特殊的方式构建你的DLL.我希望您WAVEFORMATEX从Windows头文件中获取并且他们已经为该结构指定了包装.
如果您仍然卡住,那么您应该显示成功的C++调用代码.
从评论来看,你的代码中仍然存在一个错误.在这种情况下,特别是当您怀疑互操作时,进行简单的再现以确定互操作是否是问题是值得的.这是我的:
C++ DLL
#include <Windows.h>
#include <mmsystem.h>
#include <iostream>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) int __stdcall myFun(void * const context,
const char * const pszFileName, const unsigned int buffSize,
void * const pWaveFormatex)
{
std::cout << context << std::endl
<< pszFileName << std::endl
<< buffSize << std::endl;
WAVEFORMATEX wfx;
wfx.cbSize = 1;
wfx.nAvgBytesPerSec = 2;
wfx.nBlockAlign = 3;
wfx.nChannels = 4;
wfx.nSamplesPerSec = 5;
wfx.wBitsPerSample = 6;
wfx.wFormatTag = 7;
CopyMemory(pWaveFormatex, &wfx, sizeof(wfx));
return 666;
}
Run Code Online (Sandbox Code Playgroud)
C#控制台应用
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication13
{
class Program
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
public ushort cbSize;
}
[DllImport(@"Win32Project1.dll", EntryPoint = "?myFun@@YGHQAXQBDI0@Z")]
public static extern int myFun(
IntPtr context,
string fileName,
uint bufferSize,
out WAVEFORMATEX wfx
);
static void Main(string[] args)
{
WAVEFORMATEX wfx;
int result = myFun((IntPtr)42, @"C:\video.wmv", 176400, out wfx);
Console.WriteLine(result);
Console.WriteLine(wfx.cbSize);
Console.WriteLine(wfx.nAvgBytesPerSec);
Console.WriteLine(wfx.nBlockAlign);
Console.WriteLine(wfx.nChannels);
Console.WriteLine(wfx.nSamplesPerSec);
Console.WriteLine(wfx.wBitsPerSample);
Console.WriteLine(wfx.wFormatTag);
Console.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
产量
0000002A C:\video.wmv 176400 666 1 2 3 4 5 6 7