Search code examples
c#c++pinvokeautocadobjectarx

C# wrapper for acdbEntGet and acdbEntGetX


I need a wrapper for acdbEntGet and acdbEntGetX in C#. These functions are located in accore.dll (AutoCAD 2014) and I've tried this:

[DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "acdbEntGetX")]
public static extern IntPtr acdbEntGetX(Int64 e, IntPtr app);

[DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto, EntryPoint = "acdbEntGet")]
public static extern IntPtr acdbEntGet(Int64 e);

The return value (a IntPtr) is always 0 from both functions. No errors or exceptions.

Almost every ObjectARX C++ functions are wrapped in the C# managed libraries, but those two functions are not. I wonder why.

Oh, and someone may ask why I need those functions... The answer is that I would like to return a list to Lisp which can be given directly to (entmake) without modifications. That's done with acdbEntGet and acdbEntGetX. Creating the list "by hand" is an option, but that's not what I want (and yes, I know how to create lists in C# ObjectARX) :)

Edit: Here is how these functions are defined in C++

struct resbuf *acdbEntGetX (const ads_name ent, const struct resbuf *args);
struct resbuf *acdbEntGet (const ads_name ent);

struct resbuf is a linked list defined in adsdef.h

struct resbuf {                                                  
        struct resbuf *rbnext; 
        short restype;
        union ads_u_val resval;
};

ads_name is an array of two 64-bits integers (if I remember correct)


Solution

  • Since my edit of Maxences answer was rejected, I’ll rewrite the correct solution here. I've also included the code for acdbEntGetX

    [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr acdbEntGet(AdsName objName);
    
    [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern IntPtr acdbEntGetX(AdsName objName, IntPtr app);
    
    [DllImport("acdb19.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
    static extern ErrorStatus acdbGetAdsName64(out AdsName objName, ObjectId id);
    

    Example:

    ResultBuffer app = new ResultBuffer();
    app.Add(new TypedValue((int)LispDataType.Text, "*"));
    
    AdsName name = new AdsName();
    acdbGetAdsName64(out name, o);
    
    IntPtr res = acdbEntGetX(name, app.UnmanagedObject);
    ResultBuffer rb;
    if (res != IntPtr.Zero) rb = ResultBuffer.Create(res, true);
    

    There is no need for the struct ads_name as it is in the assembly acdbmgd.dll (AdsName)