非托管C DLL结构体封送C#出现访问违规,如何修正对齐?
Hey there, let's break down why you're hitting those access violations—9 times out of 10 with interop scenarios like this, it's down to mismatched calling conventions, struct layout misalignment, or delegate memory management. Let's walk through the fixes step by step:
1. Fix Delegate Definitions (Move Them Outside the Struct)
Putting delegate types inside the struct works syntactically, but it can cause unexpected layout and marshaling issues with unmanaged code. First, define your delegates outside the struct, and explicitly set their calling convention to match your unmanaged C code (since you're using Cdecl for the DLL function, the function pointers need the same):
// Define delegates with matching calling convention first [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate void Func1Delegate(void* l, int* data); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public unsafe delegate void Func2Delegate(void* l, int* data);
2. Correct Struct Layout and Members
Next, adjust your struct to match the unmanaged myStructure exactly. The key here is setting the correct packing to avoid memory alignment mismatches—this is a super common cause of access violations:
[StructLayout(LayoutKind.Sequential, Pack = 1)] // Pack=1 matches default C struct alignment (unless your C code uses custom packing) public unsafe struct myStructure { // Use the delegate types we defined earlier public Func1Delegate Func1; public Func2Delegate Func2; }
If your C code uses a custom packing (like #pragma pack(4)), update the Pack value to match that number. This ensures every member in the C# struct lines up perfectly with the unmanaged one in memory.
3. Verify DllImport Declaration
Your functionInterface declaration is mostly right, but double-check the calling convention and make sure you're using unsafe correctly (since we're dealing with pointers):
[DllImport("lib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern unsafe void functionInterface(ref myStructure pToStruct);
Also, critical: Make sure your C# project's platform target (x86/x64) matches the architecture of your unmanaged DLL. A 64-bit C# app calling a 32-bit DLL (or vice versa) will almost always throw access violations due to mismatched pointer sizes.
4. Manage Delegate Lifetime (Prevent GC Collection)
If the unmanaged code stores the function pointers for later use (not just during the functionInterface call), your delegates might get garbage collected, leading to random access violations. To fix this, store the delegate instances in a long-lived variable (like a class-level field):
// Keep these alive to prevent GC from collecting the delegates private static Func1Delegate _func1Instance; private static Func2Delegate _func2Instance; public unsafe void CallUnmanagedFunction() { // Initialize delegates and assign them to the struct _func1Instance = MyFunc1Implementation; _func2Instance = MyFunc2Implementation; myStructure structInstance = new myStructure { Func1 = _func1Instance, Func2 = _func2Instance }; // Call the unmanaged function functionInterface(ref structInstance); } // Your C# implementations of the delegate methods private unsafe void MyFunc1Implementation(void* l, int* data) { // Add your logic here } private unsafe void MyFunc2Implementation(void* l, int* data) { // Add your logic here }
If the unmanaged code only uses the pointers during the functionInterface call, you can get away with local variables, but storing them long-term is safer for most interop scenarios.
Quick Additional Checks
- If your C code uses
__stdcallinstead ofcdecl(unlikely here since you specifiedCdecl), update theCallingConventionin both delegates andDllImport. - Double-check that the
void* lparameter in your delegates is handled correctly—don't dereference it unless you know exactly what type of pointer it points to.
内容的提问来源于stack exchange,提问作者Denis

