Marshaling from C# to Oper* arguments in XLL

98 views
Skip to first unread message

Beastian

unread,
Aug 29, 2014, 11:38:10 AM8/29/14
to exce...@googlegroups.com
I have an old XLL written in C which I'd like to wrap into a C# class library. I am able to invoke any of these functions which take a "void" argument successfully and marshal the result using:

1) A modified version of the ExcelDnaLoader project from the ExcelDna solution using the XLOper class and its marshalers. (Thanks Govert.)

I cannot however invoke any of the methods that take a "Oper*" arguments without unbalancing the stack.

I tried writing an Oper" struct in C#:

 [StructLayout(LayoutKind.Explicit)]
    public unsafe struct Oper
    {
        [StructLayout(LayoutKind.Explicit)]
        unsafe public struct OperArray // In OPER
        {
            [FieldOffset(0)]
            public Oper* pOpers;
            [FieldOffset(4)]
            public ushort Rows;
            [FieldOffset(6)]
            public ushort Columns;
        }
        [FieldOffset(0)]
        public double numValue; // In OPER
        [FieldOffset(0)]
        public XlString* pstrValue; // In OPER
        [FieldOffset(0)]
        public ushort boolValue; // In OPER
        [FieldOffset(0)]
        public ushort /*ExcelError*/ errValue; // In OPER
        [FieldOffset(8)]
        public XlType xlType; // In OPER
    }

Whereas in C the Oper struct is defined as:

typedef struct _oper
{
    union
    {
        double num;                     /* xltypeNum */
        LPSTR str;                      /* xltypeStr */
        WORD boolean;                   /* xltypeBool */
        WORD err;                       /* xltypeErr */
        struct
        {
            struct _oper *lparray;
            WORD rows;
            WORD columns;
        } array;                        /* xltypeMulti */
    } val;
    WORD type;
} OPER, *LPOPER ;

I tried passing an argument to:

unsafe delegate IntPtr UdfDelegate(Oper* a1);

which points to the C function:

XLFUNC(LPXLOPER) CDS_Test2(Oper* a1)

However this crashes with a complaint that the stack is unbalanced because the signatures don't match. Does anyone have any idea of how to do this properly?

Beastian

unread,
Aug 29, 2014, 4:09:37 PM8/29/14
to exce...@googlegroups.com
Looks like:

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        unsafe delegate IntPtr UdfDelegate4(IntPtr a1);

Solves this issue.

Naju Mancheril

unread,
Aug 29, 2014, 4:34:38 PM8/29/14
to exce...@googlegroups.com
Thanks for posting the solution!

This project sounds really interesting. Is it your plan to provide an ExcelDna addin that implements some (newer?) functions in .NET and redirects the other functionality to an older compiled XLL file?

In any event, this would could provide a good migration path for people with old XLL files who want to move to ExcelDna. If possible, please post your class library (or a slimmed down version of it) on github. Future developers will thank you.

Beastian

unread,
Sep 2, 2014, 11:46:23 AM9/2/14
to exce...@googlegroups.com
I'd be happy to post more detailed instructions once I'm done, but I'm still experimenting. I am simply taking Govert's nice marshaling library "ExcelDNA.Loader" and using its member methods to marshal inputs into and out of my C library. Each function you need will have to be wrapped and memory copying and subsequent done on the inputs as Govert's marshaler declares just one static instance of the IntPtr. I'll gather my thoughts when I'm done with my C# wrapped library.
Reply all
Reply to author
Forward
0 new messages