Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 472521
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 13, 20262026-05-13T00:05:44+00:00 2026-05-13T00:05:44+00:00

I hope someone can assist me with the problem I’m currently experiencing. We have

  • 0

I hope someone can assist me with the problem I’m currently experiencing. We have a lot of Delphi legacy code, and need to convert some of our Delphi applications to C#.

The legacy code I’m currently struggling with is that of calling a function from a 3rd party application’s non-COM DLL.

Here is the C-style header and struct used for the specific function:

/*** C Function AwdApiLookup ***/  
extern BOOL APIENTRY AwdApiLookup( HWND hwndNotify, ULONG ulMsg,  
                                   BOOL fContainer, CHAR cObjectType,  
                                   SEARCH_CRITERIA* searchCriteria,  
                                   USHORT usCount, USHORT usSearchType,  
                                   VOID pReserved );  

/*** C Struct SEARCH_CRITERIA ***/  
typedef struct _search_criteria  
{  
    UCHAR dataname[4];  
    UCHAR wildcard;  
    UCHAR comparator[2];  
    UCHAR datavalue[75];  
} SEARCH_CRITERIA;  

In our Delphi code, we have converted the above function and structure as:

(*** Delphi implementation of C Function AwdApiLookup ***)
function AwdApiLookup(hwndNotify: HWND; ulMsg: ULONG; fContainer: Boolean;
    cObjectType: Char; pSearchCriteria: Pointer; usCount: USHORT;
    usSearchType: USHORT; pReserved: Pointer): Boolean; stdcall;
    external 'AWDAPI.dll';

(*** Delphi implementation of C Struct SEARCH_CRITERIA ***)
TSearch_Criteria = record
    dataname:   array [0..3] of char;
    wildcard:   char;
    comparator: array [0..1] of char;
    datavalue:  array [0..74] of char;
end;
PSearch_Criteria = ^TSearch_Criteria;

and the way we call the above mentioned code in Delphi is:

AwdApiLookup(0, 0, true, searchType, @criteriaList_[0], 
             criteriaCount, AWD_USE_SQL, nil);

where criteriaList is defined as

criteriaList_: array of TSearch_Criteria;

After all that is said and done we can now look at the C# code, which I cannot get to work. I’m sure I’m doing something wrong here, or my C header is not translated correctly. My project does compile correctly, but when the function is called, I get a “FALSE” value back, which indicates that the function did not execute correctly in the DLL.

My C# code thus far:

/*** C# implementation of C Function AwdApiLookup ***/
DllImport("awdapi.dll", CharSet = CharSet.Auto)]
public static extern bool AwdApiLookup(IntPtr handle, ulong ulMsg, 
                                       bool fContainer, char cObjectType, 
                                       ref SearchCriteria pSearchCriteria, 
                                       ushort usCount, ushort usSearchType, 
                                       Pointer pReserverd);

/*** C# implementation of C Struct SEARCH_CRITERIA ***/
[StructLayout(LayoutKind.Sequential)]
public struct SearchCriteria
{
    private readonly byte[] m_DataName;
    private readonly byte[] m_Wildcard;
    private readonly byte[] m_Comparator;
    private readonly byte[] m_DataValue;

    public SearchCriteria(string dataName, string comparator, string dataValue)
    {
        m_DataName = Encoding.Unicode.GetBytes(
                                dataName.PadRight(4, ' ').Substring(0, 4));
        m_Wildcard = Encoding.Unicode.GetBytes("0");
        m_Comparator = Encoding.Unicode.GetBytes(
                                    comparator.PadRight(2, ' ').Substring(0, 2));
        m_DataValue = Encoding.Unicode.GetBytes(
                                    dataValue.PadRight(75, ' ').Substring(0, 75));
    }

    public byte[] dataname { get { return m_DataName; } }
    public byte[] wildcard { get { return m_Wildcard; } }
    public byte[] comparator { get { return m_Comparator; } }
    public byte[] datavalue { get { return m_DataValue; } }
}

My C# call to the C# function looks like this

var callResult = UnsafeAwdApi.CallAwdApiLookup(IntPtr.Zero, 0, true, 'W', 
                                               ref searchCriteria[0], criteriaCount,
                                               66, null);

where searchCriteria and criteriaCount is defined as

List<SearchCriteria> criteriaList = new List<SearchCriteria>();
var searchCriteria = criteriaList.ToArray();
var criteriaCount = (ushort)searchCriteria.Length;

and adding data to searchCriteria:

public void AddSearchCriteria(string dataName, string comparator, string dataValue)
{
    var criteria = new SearchCriteria();
    criteria.DataName = dataName;
    criteria.Wildcard = "0";
    criteria.Comparator = comparator;
    criteria.DataValue = dataValue;
    criteriaList.Add(criteria);
}

Like I said, my code compiles correctly, but when the function executes, it returns “FALSE”, which should not be the case as the Delphi function does return data with the exact same input.

I know I’m definitely doing something wrong here, and I’ve tried a couple of things, but nothing seems to be working.

Any assistance or nudge in the right direction would be greatly appreciated.

Thanks, Riaan

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-13T00:05:44+00:00Added an answer on May 13, 2026 at 12:05 am

    Several things here.

    First of all C++ ULONG is a 32-bit integer, and becomes uint in C# – ulong is 64-bit.

    For the struct, you don’t need to mess with byte arrays. Use strings, and ByValTStr. Also, it’s not really worth bothering with readonly and properties for interop structs. Yes, mutable value types are generally bad in a pure .NET API, but in this case it’s the existing API, there’s no point in masking it. So:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct SearchCriteria
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4]
        public string m_DataName;
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1]
        public string m_Wildcard;
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2]
        public string m_Comparator;
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 75]
        public string m_DataValue;
    }
    

    If you really want to do all the string conversions yourself, it may be easier to just use unsafe and fixed-size arrays:

    public unsafe struct SearchCriteria
    {
        public fixed byte m_DataName[4];
        public byte m_Wildcard;
        public fixed byte m_Comparator[2];
        public fixed byte m_DataValue[75];
    }
    

    [EDIT] Two more things.

    CHAR cObjectType should become byte cObjectType, and not char cObjectType that you currently use.

    Also, yes, there is a problem with array marshaling in your example. Since your P/Invoke declaration is ref SearchCriteria pSearchCriteria – i.e. a single value passed by reference – that’s precisely what P/Invoke mashaler will do. Keep in mind that, unless your struct only has fields of unmanaged types in it (the one with fixed arrays above is that, the one with string is not), the marshaler will have to copy the structs. It won’t just pass address to the first element of the array directly. And in this case, since you didn’t tell it it’s an array there, it will only copy the single element you reference.

    So, if you use the version of the struct with string, fields, you need to change the P/Invoke declaration. If you only need to pass SEARCH_CRITERIA objects into the function, but won’t need to read data from them after it returns, just use an array:

    public static extern bool AwdApiLookup(IntPtr handle, uint ulMsg, 
                                           bool fContainer, byte cObjectType, 
                                           SearchCriteria[] pSearchCriteria, 
                                           ushort usCount, ushort usSearchType, 
                                           Pointer pReserverd);
    

    And call it like this:

    var callResult = UnsafeAwdApi.CallAwdApiLookup(
        IntPtr.Zero, 0, true, (byte)'W', 
        searchCriteria, criteriaCount,
        66, null);
    

    If function writes data into that array, and you need to read it, use [In, Out]:

    [In, Out] SearchCriteria[] pSearchCriteria, 
    

    If you use the version with fixed byte[] arrays, you can also change the P/Invoke declaration to read SearchCriteria* pSearchCriteria, and then use:

    fixed (SearchCriteria* p = &searchCriteria[0])
    {
        AwdApiLookup(..., p, ...);
    }
    

    This will require unsafe as well, though.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

hope someone can help with this. I currently have an Add to Cart option
I hope someone can help me with the following... I have this code below
I really hope someone can help with this problem. I have an ajax pagination
Hope someone can help. I have the code below which when the user hovers
hope someone can help. I have two tables: Users -UserID -UserName UsersType -UserTypeID -UserID
Hope someone can help me out with this problem I am having. I just
I hope someone can guide me as I'm stuck... I need to write an
Hope someone can help me with this.. I have a magento store up&running, via
Hope someone can help, I'm not a programmer, but have been interested in exploring
Hope someone can help. I have a simple scenario where clicking checkboxes is driving

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.