DLL interop / interesting error - c++

char ARRAY[1024]; // <-- global
Code below works
myFunctionInDll("some string"); // everything ok
Code below doesn't work
myFunctionInDll(ARRAY); // after compilation the entry point of DLL cannot be found
So, to sum up, if I pass a "static string" to my function inside my dll the dll compiles and loads perfectly. However, if I populate the global array (chars) and then try and pass that to my function, again it compiles but when I try and call the function from my C# app I get 'entry point cannot be found.' This is really strange and I can find no reason why...
Thanks RU.
Anyone know why?

Did you write the interop or are you just using the .NET generated interop class? If the later try
string myStr = "some string";
myFunctionInDll(myStr);
Hope that helps.

Related

Can't find COM object from C++, although Guid it's registered

First of all happy new year to everyone, hope you're doing well!
I'm working on a C++ project in which I need to call a C# DLL I created following the first answer of this post. Once I have the DLL, I need to call it from Qt, so by using dumpcpp and the .tlb file generated by regasm, I managed to get the .cpp and .h files to use my classes. Just as a reference, the namespace of the classes is Wrapper, and the main class is Device with guid {DD4A4896-C105-4C60-839B-B18C99C8FE15}.
Once I have the generated files to use the DLL, if I try to create a Wrapper:: Device instance on Qt, I get the following error:
QAxBase::setControl: requested control {dd4a4896-c105-4c60-839b-b18c99c8fe15} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
It doesn't give any more information, so I tried to check if the guid was stored on the system registry (I used the regasm command explained on the previously quoted post, and It said that it was successful, but you never know). Opening Registry editor and searching for the Guid revealed that it's present at: Computer\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{DD4A4896-C105-4C60-839B-B18C99C8FE15}, which, as far as I know, is the right route for these guids, and it points to the right DLL.
I though It may be due to some kind ActiveQt problem, and as the previously quoted post explained how to use that DLL from VS C++, I decided to give it a try, using this as an another reference. I've finished with this code, which is supposed to create an instance of my Device object
#include <iostream>
#include <atlstr.h>
#import "C:\Users\javie\Documents\Wrapper\Wrapper\bin\x86\Release\netstandard2.0\Wrapper.tlb" named_guids raw_interfaces_only
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
int main()
{
try
{
TESTHR(CoInitialize(0));
Wrapper::IDevicePtr devPtr = nullptr;
TESTHR(devPtr.CreateInstance("{DD4A4896-C105-4c60-839B-B18C99C8FE15}"));
}
catch (const _com_error& e)
{
CStringW out;
out.Format(L"Exception occurred. HR = %lx, error = %s", e.Error(), e.ErrorMessage());
MessageBoxW(NULL, out, L"Error", MB_OK);
}
CoUninitialize();// Uninitialize COM
std::cout << "Hello World!\n";
}
However, this doesn't work either, the createInstance method throws an exception of Class not registered and HR=80040154. Again, according to Registry editor, the class is registered, so I don't understand the error. I've also tried with devPtr.CreateInstance("Wrapper.Device"), devPtr.CreateInstance("Wrapper::Device") or `devPtr.CreateInstance("Wrapper::CLSID_Device") as the links I posted suggest, but in those cases I get another exception with HR=800401f3 and message Invalid class string.
It doesn't matter whether VS or Qt Creator are opened as administrator or not, I get the exact same error.
I have run out of ideas, and I really need to be able to use that DLL from Qt using the files generated by dumpcpp.
Does any one know what could be happening? It feels quite strange to me.
If your C++ application is 64-bit, that's the answer right there, because your C# component is 32-bit (or MSIL but registered to the 32-bit hive). In situations like these, a simple test using VBScript is always useful.
Write a simple VB Script (test.vbs)
Dim obj
Set obj = CreateObject("Wrapper.Device") ' or whatever your ProgID is
MsgBox TypeName(obj)
Now, run this macro 2 ways: with 32-bit and 64-bit versions of VBScript:
32-bit > c:\windows\SysWow64\cscript.exe test.vbs
64-bit > c:\windows\system32\cscript.exe test.vbs
This is assuming your C# component is dispatch compatible. If it's not, then it will still give you differing results that you can use to debug.
Assuming automation/IDispatch compatible, one will work and one won't if you have registered your component correctly.
Have you registered correctly? When I use regasm, I always use the the switches /tlb /codebase when registering the C# component for COM.
Ok, in case someone find the same error, I'll explain the solution I found.
The problem was that in my case, the C# class I developed depended on another 32 bits dll which was not registered on my PC. Once I registered the other dll, everything worked fine.
I don't know why VS kept telling me that the class was not registered when my class itselft was registered, it was one of its dependencies that wasn't registered.
Anyway, I discovered this thanks to Joseph's comments, so thanks a lot for your help.

why vba can't successfully call dll that's written in c++?

I got a c++ demo that has successfully called the API written in c++, now am trying to call those API from excel VBA. I've done quite a bit research but still not able to link them together.
Basically there's a API(TapQuoteAPI.dll) export function like this in demo
'TapQuote.h
TAP_DLLEXPORT const TAPICHAR *TAP_CDECL GetTapQuoteAPIVersion();
in demo c++ solution(TapQuoteAPI_Demo), i include the 'TapQuote.h' in demo.cpp,
the cout<<GetTapQuoteAPIVersion()<<endl; is successfully called, and result is print.
but when it comes to call this function in excel vba, i keep failing.
I tried to directly use the TapQuoteAPI.dll in excel like this, but not working.
Declare Function GetTapQuoteAPIVersion Lib "D:\Proejct\WIN32\TapQuoteAPI.dll" () As String
Then I also try to build another dll function with a deFile.def from TapQuoteAPI_Demo.dll since i successfully call it within the c++ demo.
Declare Function GetTapQuoteAPIVersion Lib "D:\Proejct\WIN32\TapQuoteAPI_demo.dll" () As String
also failed.
Could anyone shed some lights for me please?

Crash on returning a System::String that was marshalled from a native C++ call

I have a native C++ dll which I call from a managed c++ dll which is called from a C# application.
The function in the native dll looks something like this:
std::string NativeClass::Test()
{
return std::string("some string");
}
The managed C++ function that calls it looks something like this
String ^ ManagedClass::Test()
{
std::string temp = this->_native->Test();
String^ sRet = msclr::interop::marshal_as<String^>(temp);
return sRet; // crashes here !!!
}
However, on executing the return statement, the application crashes with an error like
Debug Assertion Failed!
debug_heap.cpp
Line 980
Expression: __acrt_first_block == header
I looked all over Stackoverflow but I've not solved it yet. Any ideas?
Hans helped solved this. It was indeed a mismatch between the CRT versions in the native dll and managed dll. I was sure I had already checked this but obviously missed it. The code otherwise works as is. Thanks.

Compiling old C++ classes under Borland C++Builder XE

Currently, I'm working on compiling old .cpp classes under C++ Builder XE. Apart from many troubles, there is one which I have completely no idea how to solve.
My code:
String txt = "<Not so long sql query>";
int licz = some_function(txt, dzeFDS); //1
//assigning licz to somewhere
txt = "<much longer query>";
licz = some_function(txt, budFDS); //2
Problem is that during second call of some_function program is stopped and i have this alert:
First chance exception at $75A1C42D. Exception class EDatabaseError with message 'budFDS: Type mismatch for field 'Function', expecting: String actual: WideString'. Process Call.exe (1896)
It's strange form be, bacause first call of some_function works fine, but this second one (with arguments with the same type) doesn't.
some_function code:
int __fastcall some_function(String txt, TIBDataSet *firDS)
{
firDS->Close();
firDS->SelectSQL->Text = txt;
firDS->Open(); //during debugging, exception occurs in this line
int count = 0;
while(!firDS->Eof)
{ count++;
firDS->Next();
}
return count;
}
Any ideas what why it happens?
Thanks in advance
There is much pain in your future.
Anyway, the problem you're having is with the database connection. There's a field in your database called "Function" that holds a string. This field came across as a String with the ancient database driver that this program originally used. Your shiny, new database driver is telling VCL to expect such things as Unicode, and VCL doesn't like to shove such things into plain Strings, so it expects you to have a WideString ready in which to shove it.
Fortunately, there are ways of beating VCL into submission. What you want to do, since you surely don't want to rewrite half the application by changing TIBDataSet, is to tell the connection not to bother with Unicode. In order to do this, you have to set up the TSQLConnection object with UseUnicode=false, which I hope (I have no way of testing VCL code anymore) should look something like this:
connection->Params->Add("UseUnicode=false");
Where connection is the TSQLConnection object. I think you have to do this before connecting to the database.
If that doesn't work, see if you can configure the database driver to not use Unicode.
Problem solved - this one field Function has other type in C++ Builder design view - it was TStringField, and rest fields has TIBStringField...

strange error in Eclipse

hello everyone I have this snippet of the code:
void* Init(int N) {
Hand * DS = new Hand(N);
return (void*)DS;
//DS is static defined somewhere...
every time when I check in Debugger I receive the same error:
mi_cmd_var_create: unable to create variable objec
can somebody please explain why?
P.S. I know that this implementation of the function is not good, but it is what I have... Constructor of the Hand works perfectly!
This guy with the same problem solved it like:
If you have variables in your watch
window that you later eliminate from
your code then attempt to debug again
this error is generated. The fix is to
also delete the variable from the
watch list. At least this is how it
works in Eclipse Europa.