I am working on an app that deals with external hardware communication, and I'm having problem getting checksum of a package. (I'm still learning objective C while making this app, so I'm still fairly new in this.)
In another code written in C, the checksum was calculated like this:
byte CalculateCheckSum (byte txcount){
byte local_cs=0;
while(txcount>0){
local_cs+=*x_ptr;
x_ptr += 1;
txcount--;
};
return (~local_cs+1);
}
I tried to use the some code for objective C:
u_int8_t synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
- (Byte)CalcCheckSum:(Byte)i
{ u_int8_t synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
Byte local_cs = 0;
int j = 0;
while (i>0) {
local_cs += synByteSOH[j];
i--;
j++;
};
return (~local_cs+1);
}
No warnings or errors, but it's said clang: error: linker command failed with exit code 1
Does anyone know why is that? And how should I fix it?
All valid C code it valid Objective C code. Don't try rewriting it into a Objective C method - there's zero value to that.
The trick to adapting the original function is that it relies on several things: byte being typedeffed, and a global/static variable called x_ptr.
About x_ptr, where it comes from and how is it initialized in the original, we know nothing from the pasted snippet. So assuming that the byte array synByteSOH is the data block you need a checksum of, just introduce a file static variable x_ptr of type byte* and initialize it to your data block:
typedef unsigned char byte;
static byte *x_ptr;
byte CalculateCheckSum (byte txcount)
//...Follows as pasted
//...
//And now we call it elsewhere:
byte synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
x_ptr = synByteSOH
byte Checksum = CalculateCheckSum(4); //4 is the data block size
In general, even in an ObjC project it's perfectly OK to have C functions. No one ever said every piece of code should be in a class method.
Related
I have a C++ COM local server and C# client. The server code:
// MyStruct as define in the _i.h file
typedef /* [uuid] */ DECLSPEC_UUID("...") struct MyStruct
{
SAFEARRAY * FormatData;
LONG aLong;
BOOL aBool;
} MyStruct;
// Server method being invoked
STDMETHODIMP CMyClass::Foo(MyStruct* StreamInfo, int* result)
{
long Length;
BYTE* Data;
GetData(Length, Data);
PackBytes(Length, Data, &(StreamInfo->FormatData));
}
PackBytes converts the BYTE array to SAFEARRAY. It is taken from this stackoverflow question. It sets the boundary & dimension of the SAFEARRAY.
The client code:
MyStruct myStruct;
int rc = obj.Foo(out myStruct);
Where MyStruct is imported from the COM assembly. it appears as
public struct MyStruct
{
public Array FormatData;
int aLong;
int aBool;
}
After running Foo appears the error "SafeArray cannot be marshaled to this array type because it has either nonzero lower bounds or more than one dimension" with additional remark "Make sure your array has the required number of dimensions".
When debugging the server code it seems Data is properly populated in FormatData: as can be seen in screen-shot below. cElements equals Length and the 18 data pieces are equal to the ones in Data.
Hard-coding Length = 1 did not help. Removing the PackByets call made the error disappear (other fields were passed ok). How can this be fixed?
The PackBytes method that you have referenced constructs a SAFEARRAY with lower bound of 1. Constructing it with a lower bound of zero may fix the problem:
SAFEARRAYBOUND bound{ count, 0 };
I haven't seen C++ code in more than 10 years and now I'm in the need of developing a very small DLL to use the Ping class (System::Net::NetworkInformation) to make a ping to some remoteAddress.
The argument where I'm receiving the remoteAddress is a FREObject which then needs to be transformed into a const uint8_t *. The previous is mandatory and I can't change anything from it. The remoteAddress has to be received as a FREObject and later be transformed in a const uint8_t *.
The problem I'm having is that I have to pass a String^ to the Ping class and not a const uint8_t * and I have no clue of how to convert my const uint8_t * to a String^. Do you have any ideas?
Next is part of my code:
// argv[ARG_IP_ADDRESS_ARGUMENT holds the remoteAddress value.
uint32_t nativeCharArrayLength = 0;
const uint8_t * nativeCharArray = NULL;
FREResult status = FREGetObjectAsUTF8(argv[ARG_IP_ADDRESS_ARGUMENT], &nativeCharArrayLength, &nativeCharArray);
Basically the FREGetObjectAsUTF8 function fills the nativeCharArray array with the value of argv[ARG_IP_ADDRESS_ARGUMENT] and returns the array's length in nativeCharArrayLength. Also, the string uses UTF-8 encoding terminates with the null character.
My next problem would be to convert a String^ back to a const uint8_t *. If you can help with this as well I would really appreciate it.
As I said before, non of this is changeable and I have no idea of how to change nativeCharArray to a String^. Any advice will help.
PS: Also, the purpose of this DLL is to use it as an ANE (Air Native Extension) for my Adobe Air app.
You'll need UTF8Encoding to convert the bytes to characters. It has methods that take pointers, you'll want to take advantage of that. You first need to count the number of characters in the converted string, then allocate an array to store the converted characters, then you can turn it into System::String. Like this:
auto converter = gcnew System::Text::UTF8Encoding;
auto chars = converter->GetCharCount((Byte*)nativeCharArray, nativeCharArrayLength-1);
auto buffer = gcnew array<Char>(chars);
pin_ptr<Char> pbuffer = &buffer[0];
converter->GetChars((Byte*)nativeCharArray, nativeCharArrayLength-1, pbuffer, chars);
String^ result = gcnew String(buffer);
Note that the -1 on nativeCharArrayLength compensates for the zero terminator being included in the value.
I should use Objective-C to read some slowly growing file (under Mac OS X).
"Slowly" means that I read to EOF before it grows bigger.
In means of POSIX code in plain syncronous C I can do it as following:
while(1)
{
res = select(fd+1,&fdset,NULL,&fdset,some_timeout);
if(res > 0)
{
len = read(fd,buf,sizeof(buf));
if (len>0)
{
printf("Could read %u bytes. Continue.\n", len);
}
else
{
sleep(some_timeout_in_sec);
}
}
}
Now I want to re-write this in some asynchronous manner, using NSInputSource or some other async Objective-C technique.
The problem with NSInputSource: If I use scheduleInRunLoop: method then once I get NSStreamEventEndEncountered event, I stop receiving any events.
Can I still use NSInputSource or should I pass to using NSFileHandle somehow or what would you recommend ?
I see a few problems.
1) some_Timeout, for select() needs to be a struct timeval *.
2) for sleep() some_timeout needs to be an integer number of seconds.
3) the value in some_timeout is decremented via select() (which is why the last parameter is a pointer to the struct timeval*. And that struct needs to be re-initialized before each call to select().
4) the parameters to select() are highest fd of interest+1, then three separate struct fd_set * objects. The first is for input files, the second is for output files, the third is for exceptions, however, the posted code is using the same struct fd_set for both the inputs and the exceptions, This probably will not be what is needed.
When the above problems are corrected, the code should work.
I am a developer in C-like languages (Java/JavaScript/C#) and I am attempting to convert some Objective-C code into Java.
For the most part, it is relatively straightforward but I have hit a stumbling block with the following bit of code:
typedef struct {
char *PAGE_AREA_ONE;
char *PAGE_AREA_TWO;
char *PAGE_AREA_THREE;
} CODES;
- (CODES*) getOpCode {
CODES *result = NULL;
result = malloc(sizeof(CODES));
result->PAGE_AREA_ONE = "\x1b\x1b\x1b";
result->PAGE_AREA_TWO = "\x2d\x2d\x2d";
result->PAGE_AREA_THREE = "\x40\x40";
return result;
}
What would the Java equivalent of this be? From what I can tell in other areas of the code, it is being used to store constants. But I am not 100% certain.
Thanks.
The typedef is just creating a structure that contains three string properties. The getOpCode method is apparently trying to create a new structure and assign values to those three properties. C# code would be:
public class Codes
{
public string PageAreaOne;
public string PageAreaTwo;
public string PageAreaThree;
}
public Codes GetCodes()
{
Codes result = new Codes();
result.PageAreaOne = "\x1b\x1b\x1b"; // three ESC characters
result.PageAreaTwo = "---";
result.PageAreaThree = "##";
return result;
}
The code in question is allocating a block of memory that the size of the CODES structure, filling it with some data, and returning a pointer to the new block. The data is apparently some operation codes (that is, instructions) for something, so perhaps the data is being sent to some other device where the instructions will be executed.
I have what looks to me an innocent cycle which iterates on elements of an array whose type is unknown at compile time; my array is named mesh->vertices and is a pointer to void. Depending on the truth value of mesh->textured I need to consider the array differently. Incidentally, the code in the if and the else in the code segment below is similar, but I do need to distinguish two cases.
void TransformMesh(struct Mesh *mesh, struct Matrix4 *t)
{
for (int i = 0; i < mesh->nVertices; ++i)
{
if (mesh->textured)
{
struct TexturedVertex *ptr = ((struct TexturedVertex *)mesh->vertices) + i;
ptr[i].position = MatrixPointMultiply3(t, &ptr->position);
ptr[i].normal = MatrixPointMultiply3(t, &ptr->normal);
}
else
{
struct Vertex *ptr = ((struct Vertex *)mesh->vertices) + i;
ptr[i].position = MatrixPointMultiply3(t, &ptr->position);
ptr[i].normal = MatrixPointMultiply3(t, &ptr->normal);
}
}
}
I guess I created the project with the Automatic Reference Counting option, thinking that it would not have affected C code, but now I feel like I'm wrong (by the way, how can I check which option I chose?).
Well, it looks like this function is doing something wrong with another array, called mesh->triangles, probably freeing it. When I try to use the vector I get an EXC_BAD_ACCESS error:
glDrawElements(GL_TRIANGLES, mesh->nTriangles * 3, GL_UNSIGNED_INT, mesh->triangles);
It looks like iterating on the mesh->vertices elements, casting them and doing the pointer arithmetic, is corrupting the memory. I think my problem is ARC, so I tried to do what described here but with no luck.
EDIT:
The code above was wrong, as pointed out by Conrad Shultz; the following is correct:
ptr->position = MatrixPointMultiply3(t, &ptr->position);
ptr->normal = MatrixPointMultiply3(t, &ptr->normal);
I seriously doubt ARC has anything to do with this - ARC only manages Objective-C objects. (It doesn't even know how to handle Core Foundation types, which leads to the requirement for using the __bridge... keywords.)
I'm struggling to understand your code. Admittedly, I don't do a great deal of straight C programming, but I don't get what you're trying to do by adding i to ptr, which is presumably the pointer arithmetic of which you speak.
Are you trying to just access the ith struct TexturedVertex in mesh->vertices? If so, just use your ptr[i] construct as written.
It looks to me like you are doing arithmetic such that ptr ends up pointing to the ith struct TexturedVertex, then by accessing ptr[i] you are reading i elements past the ith struct TexturedVertex. If nVertices refers to the count of vertices (as would seem logical, given the name and C array conventions), you are then reading past the end of vertices, a classic buffer overflow error, which would unsurprisingly lead to EXC_BAD_ACCESS and all sorts of other fun errors.